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
80 using namespace com::sun::star
;
82 using ::boost::shared_ptr
;
83 using ::com::sun::star::uno::Sequence
;
84 using ::com::sun::star::uno::Reference
;
85 using ::com::sun::star::uno::UNO_QUERY
;
86 using ::com::sun::star::uno::Any
;
87 using ::com::sun::star::sheet::DataPilotTableHeaderData
;
88 using ::com::sun::star::sheet::DataPilotTablePositionData
;
89 using ::com::sun::star::beans::XPropertySet
;
90 using ::rtl::OUString
;
92 // -----------------------------------------------------------------------
94 #define MAX_LABELS 256 //!!! from fieldwnd.hxx, must be moved to global.hxx
96 // -----------------------------------------------------------------------
98 #define SCDPSOURCE_SERVICE "com.sun.star.sheet.DataPilotSource"
100 // -----------------------------------------------------------------------
102 // incompatible versions of data pilot files
103 #define SC_DP_VERSION_CURRENT 6
105 // type of source data
106 #define SC_DP_SOURCE_SHEET 0
107 #define SC_DP_SOURCE_DATABASE 1
108 #define SC_DP_SOURCE_SERVICE 2
110 // -----------------------------------------------------------------------
112 //! move to a header file
113 #define DP_PROP_COLUMNGRAND "ColumnGrand"
114 #define DP_PROP_FUNCTION "Function"
115 #define DP_PROP_IGNOREEMPTY "IgnoreEmptyRows"
116 #define DP_PROP_ISDATALAYOUT "IsDataLayoutDimension"
117 //#define DP_PROP_ISVISIBLE "IsVisible"
118 #define DP_PROP_ORIENTATION "Orientation"
119 #define DP_PROP_ORIGINAL "Original"
120 #define DP_PROP_POSITION "Position"
121 #define DP_PROP_REPEATIFEMPTY "RepeatIfEmpty"
122 #define DP_PROP_ROWGRAND "RowGrand"
123 #define DP_PROP_SHOWDETAILS "ShowDetails"
124 #define DP_PROP_SHOWEMPTY "ShowEmpty"
125 #define DP_PROP_SUBTOTALS "SubTotals"
126 #define DP_PROP_USEDHIERARCHY "UsedHierarchy"
128 // -----------------------------------------------------------------------
130 USHORT
lcl_GetDataGetOrientation( const uno::Reference
<sheet::XDimensionsSupplier
>& xSource
)
132 long nRet
= sheet::DataPilotFieldOrientation_HIDDEN
;
135 uno::Reference
<container::XNameAccess
> xDimsName
= xSource
->getDimensions();
136 uno::Reference
<container::XIndexAccess
> xIntDims
= new ScNameToIndexAccess( xDimsName
);
137 long nIntCount
= xIntDims
->getCount();
139 for (long nIntDim
=0; nIntDim
<nIntCount
&& !bFound
; nIntDim
++)
141 uno::Reference
<uno::XInterface
> xIntDim
=
142 ScUnoHelpFunctions::AnyToInterface( xIntDims
->getByIndex(nIntDim
) );
143 uno::Reference
<beans::XPropertySet
> xDimProp( xIntDim
, uno::UNO_QUERY
);
146 bFound
= ScUnoHelpFunctions::GetBoolProperty( xDimProp
,
147 rtl::OUString::createFromAscii(DP_PROP_ISDATALAYOUT
) );
148 //! error checking -- is "IsDataLayoutDimension" property required??
150 nRet
= ScUnoHelpFunctions::GetEnumProperty(
151 xDimProp
, rtl::OUString::createFromAscii(DP_PROP_ORIENTATION
),
152 sheet::DataPilotFieldOrientation_HIDDEN
);
156 return static_cast< USHORT
>( nRet
);
159 // -----------------------------------------------------------------------
161 ScDPObject::ScDPObject( ScDocument
* pD
) :
167 mpTableData(static_cast<ScDPTableData
*>(NULL
)),
169 bSettingsChanged( FALSE
),
171 mnAutoFormatIndex( 65535 ),
174 mbHeaderLayout(false)
178 ScDPObject::ScDPObject(const ScDPObject
& r
) :
182 aTableName( r
.aTableName
),
183 aTableTag( r
.aTableTag
),
184 aOutRange( r
.aOutRange
),
188 mpTableData(static_cast<ScDPTableData
*>(NULL
)),
190 bSettingsChanged( FALSE
),
192 mnAutoFormatIndex( r
.mnAutoFormatIndex
),
194 nHeaderRows( r
.nHeaderRows
),
195 mbHeaderLayout( r
.mbHeaderLayout
)
198 pSaveData
= new ScDPSaveData(*r
.pSaveData
);
200 pSheetDesc
= new ScSheetSourceDesc(*r
.pSheetDesc
);
202 pImpDesc
= new ScImportSourceDesc(*r
.pImpDesc
);
204 pServDesc
= new ScDPServiceDesc(*r
.pServDesc
);
205 // xSource (and pOutput) is not copied
208 ScDPObject::~ScDPObject()
217 ScDataObject
* ScDPObject::Clone() const
219 return new ScDPObject(*this);
222 void ScDPObject::SetAlive(BOOL bSet
)
227 void ScDPObject::SetAllowMove(BOOL bSet
)
232 void ScDPObject::SetSaveData(const ScDPSaveData
& rData
)
234 if ( pSaveData
!= &rData
) // API implementation modifies the original SaveData object
237 pSaveData
= new ScDPSaveData( rData
);
240 InvalidateData(); // re-init source from SaveData
243 void ScDPObject::SetAutoFormatIndex(const sal_uInt16 nIndex
)
245 mnAutoFormatIndex
= nIndex
;
248 sal_uInt16
ScDPObject::GetAutoFormatIndex() const
250 return mnAutoFormatIndex
;
253 void ScDPObject::SetHeaderLayout (bool bUseGrid
)
255 mbHeaderLayout
= bUseGrid
;
258 bool ScDPObject::GetHeaderLayout() const
260 return mbHeaderLayout
;
263 void ScDPObject::SetOutRange(const ScRange
& rRange
)
268 pOutput
->SetPosition( rRange
.aStart
);
271 void ScDPObject::SetSheetDesc(const ScSheetSourceDesc
& rDesc
)
273 if ( pSheetDesc
&& rDesc
== *pSheetDesc
)
274 return; // nothing to do
277 DELETEZ( pServDesc
);
280 pSheetDesc
= new ScSheetSourceDesc(rDesc
);
282 // make valid QueryParam
284 pSheetDesc
->aQueryParam
.nCol1
= pSheetDesc
->aSourceRange
.aStart
.Col();
285 pSheetDesc
->aQueryParam
.nRow1
= pSheetDesc
->aSourceRange
.aStart
.Row();
286 pSheetDesc
->aQueryParam
.nCol2
= pSheetDesc
->aSourceRange
.aEnd
.Col();
287 pSheetDesc
->aQueryParam
.nRow2
= pSheetDesc
->aSourceRange
.aEnd
.Row();;
288 pSheetDesc
->aQueryParam
.bHasHeader
= TRUE
;
290 InvalidateSource(); // new source must be created
293 void ScDPObject::SetImportDesc(const ScImportSourceDesc
& rDesc
)
295 if ( pImpDesc
&& rDesc
== *pImpDesc
)
296 return; // nothing to do
298 DELETEZ( pSheetDesc
);
299 DELETEZ( pServDesc
);
302 pImpDesc
= new ScImportSourceDesc(rDesc
);
304 InvalidateSource(); // new source must be created
307 void ScDPObject::SetServiceData(const ScDPServiceDesc
& rDesc
)
309 if ( pServDesc
&& rDesc
== *pServDesc
)
310 return; // nothing to do
312 DELETEZ( pSheetDesc
);
316 pServDesc
= new ScDPServiceDesc(rDesc
);
318 InvalidateSource(); // new source must be created
321 void ScDPObject::WriteSourceDataTo( ScDPObject
& rDest
) const
324 rDest
.SetSheetDesc( *pSheetDesc
);
326 rDest
.SetImportDesc( *pImpDesc
);
327 else if ( pServDesc
)
328 rDest
.SetServiceData( *pServDesc
);
330 // name/tag are not source data, but needed along with source data
332 rDest
.aTableName
= aTableName
;
333 rDest
.aTableTag
= aTableTag
;
336 void ScDPObject::WriteTempDataTo( ScDPObject
& rDest
) const
338 rDest
.nHeaderRows
= nHeaderRows
;
341 BOOL
ScDPObject::IsSheetData() const
343 return ( pSheetDesc
!= NULL
);
346 void ScDPObject::SetName(const String
& rNew
)
351 void ScDPObject::SetTag(const String
& rNew
)
356 bool ScDPObject::IsDataDescriptionCell(const ScAddress
& rPos
)
361 long nDataDimCount
= pSaveData
->GetDataDimensionCount();
362 if (nDataDimCount
!= 1)
363 // There has to be exactly one data dimension for the description to
364 // appear at top-left corner.
368 ScRange aTabRange
= pOutput
->GetOutputRange(sheet::DataPilotOutputRangeType::TABLE
);
369 return (rPos
== aTabRange
.aStart
);
372 uno::Reference
<sheet::XDimensionsSupplier
> ScDPObject::GetSource()
378 void ScDPObject::CreateOutput()
383 BOOL bFilterButton
= IsSheetData() && pSaveData
&& pSaveData
->GetFilterButton();
384 pOutput
= new ScDPOutput( pDoc
, xSource
, aOutRange
.aStart
, bFilterButton
);
385 pOutput
->SetHeaderLayout ( mbHeaderLayout
);
387 long nOldRows
= nHeaderRows
;
388 nHeaderRows
= pOutput
->GetHeaderRows();
390 if ( bAllowMove
&& nHeaderRows
!= nOldRows
)
392 long nDiff
= nOldRows
- nHeaderRows
;
395 if ( nHeaderRows
== 0 )
398 long nNewRow
= aOutRange
.aStart
.Row() + nDiff
;
402 ScAddress
aStart( aOutRange
.aStart
);
403 aStart
.SetRow(nNewRow
);
404 pOutput
->SetPosition( aStart
);
406 //! modify aOutRange?
408 bAllowMove
= FALSE
; // use only once
413 ScDPTableData
* ScDPObject::GetTableData()
420 mpTableData
.reset(new ScDatabaseDPData(pDoc
, *pImpDesc
));
427 DBG_ERROR("no source descriptor");
428 pSheetDesc
= new ScSheetSourceDesc
; // dummy defaults
430 mpTableData
.reset(new ScSheetDPData(pDoc
, *pSheetDesc
));
433 // grouping (for cell or database data)
434 if ( pSaveData
&& pSaveData
->GetExistingDimensionData() )
436 shared_ptr
<ScDPGroupTableData
> pGroupData(new ScDPGroupTableData(mpTableData
, pDoc
));
437 pSaveData
->GetExistingDimensionData()->WriteToData(*pGroupData
);
438 mpTableData
= pGroupData
;
442 return mpTableData
.get();
445 void ScDPObject::CreateObjects()
447 // if groups are involved, create a new source with the ScDPGroupTableData
448 if ( bSettingsChanged
&& pSaveData
&& pSaveData
->GetExistingDimensionData() )
453 //! cache DPSource and/or Output?
455 DBG_ASSERT( bAlive
, "CreateObjects on non-inserted DPObject" );
457 DELETEZ( pOutput
); // not valid when xSource is changed
461 xSource
= CreateSource( *pServDesc
);
464 if ( !xSource
.is() ) // database or sheet data, or error in CreateSource
466 DBG_ASSERT( !pServDesc
, "DPSource could not be created" );
467 ScDPTableData
* pData
= GetTableData();
468 ScDPSource
* pSource
= new ScDPSource( pData
);
473 pSaveData
->WriteToSource( xSource
);
475 else if (bSettingsChanged
)
477 DELETEZ( pOutput
); // not valid when xSource is changed
479 uno::Reference
<util::XRefreshable
> xRef( xSource
, uno::UNO_QUERY
);
486 catch(uno::Exception
&)
488 DBG_ERROR("exception in refresh");
493 pSaveData
->WriteToSource( xSource
);
495 bSettingsChanged
= FALSE
;
498 void ScDPObject::InvalidateData()
500 bSettingsChanged
= TRUE
;
503 void ScDPObject::InvalidateSource()
509 ScRange
ScDPObject::GetNewOutputRange( BOOL
& rOverflow
)
511 CreateOutput(); // create xSource and pOutput if not already done
513 rOverflow
= pOutput
->HasError(); // range overflow or exception from source
515 return ScRange( aOutRange
.aStart
);
518 // don't store the result in aOutRange, because nothing has been output yet
519 return pOutput
->GetOutputRange();
523 void ScDPObject::Output( const ScAddress
& rPos
)
525 // clear old output area
526 pDoc
->DeleteAreaTab( aOutRange
.aStart
.Col(), aOutRange
.aStart
.Row(),
527 aOutRange
.aEnd
.Col(), aOutRange
.aEnd
.Row(),
528 aOutRange
.aStart
.Tab(), IDF_ALL
);
529 pDoc
->RemoveFlagsTab( aOutRange
.aStart
.Col(), aOutRange
.aStart
.Row(),
530 aOutRange
.aEnd
.Col(), aOutRange
.aEnd
.Row(),
531 aOutRange
.aStart
.Tab(), SC_MF_AUTO
);
533 CreateOutput(); // create xSource and pOutput if not already done
535 pOutput
->SetPosition( rPos
);
539 // aOutRange is always the range that was last output to the document
540 aOutRange
= pOutput
->GetOutputRange();
541 const ScAddress
& s
= aOutRange
.aStart
;
542 const ScAddress
& e
= aOutRange
.aEnd
;
543 pDoc
->ApplyFlagsTab(s
.Col(), s
.Row(), e
.Col(), e
.Row(), s
.Tab(), SC_MF_DP_TABLE
);
546 const ScRange
ScDPObject::GetOutputRangeByType( sal_Int32 nType
)
550 if (pOutput
->HasError())
551 return ScRange(aOutRange
.aStart
);
553 return pOutput
->GetOutputRange(nType
);
556 BOOL
lcl_HasButton( ScDocument
* pDoc
, SCCOL nCol
, SCROW nRow
, SCTAB nTab
)
558 return ((const ScMergeFlagAttr
*)pDoc
->GetAttr( nCol
, nRow
, nTab
, ATTR_MERGE_FLAG
))->HasButton();
561 void ScDPObject::RefreshAfterLoad()
563 // apply drop-down attribute, initialize nHeaderRows, without accessing the source
564 // (button attribute must be present)
566 // simple test: block of button cells at the top, followed by an empty cell
568 SCCOL nFirstCol
= aOutRange
.aStart
.Col();
569 SCROW nFirstRow
= aOutRange
.aStart
.Row();
570 SCTAB nTab
= aOutRange
.aStart
.Tab();
573 SCROW nOutRows
= aOutRange
.aEnd
.Row() + 1 - aOutRange
.aStart
.Row();
574 while ( nInitial
+ 1 < nOutRows
&& lcl_HasButton( pDoc
, nFirstCol
, nFirstRow
+ nInitial
, nTab
) )
577 if ( nInitial
+ 1 < nOutRows
&&
578 pDoc
->IsBlockEmpty( nTab
, nFirstCol
, nFirstRow
+ nInitial
, nFirstCol
, nFirstRow
+ nInitial
) &&
579 aOutRange
.aEnd
.Col() > nFirstCol
)
581 BOOL bFilterButton
= IsSheetData(); // when available, filter button setting must be checked here
583 SCROW nSkip
= bFilterButton
? 1 : 0;
584 for (SCROW nPos
=nSkip
; nPos
<nInitial
; nPos
++)
585 pDoc
->ApplyAttr( nFirstCol
+ 1, nFirstRow
+ nPos
, nTab
, ScMergeFlagAttr(SC_MF_AUTO
) );
587 nHeaderRows
= nInitial
;
590 nHeaderRows
= 0; // nothing found, no drop-down lists
593 void ScDPObject::BuildAllDimensionMembers()
598 pSaveData
->BuildAllDimensionMembers(GetTableData());
601 bool ScDPObject::GetMemberNames( sal_Int32 nDim
, Sequence
<OUString
>& rNames
)
603 vector
<ScDPLabelData::Member
> aMembers
;
604 if (!GetMembers(nDim
, GetUsedHierarchy(nDim
), aMembers
))
607 size_t n
= aMembers
.size();
609 for (size_t i
= 0; i
< n
; ++i
)
610 rNames
[i
] = aMembers
[i
].maName
;
615 bool ScDPObject::GetMembers( sal_Int32 nDim
, sal_Int32 nHier
, vector
<ScDPLabelData::Member
>& rMembers
)
617 Reference
< container::XNameAccess
> xMembersNA
;
618 if (!GetMembersNA( nDim
, nHier
, xMembersNA
))
621 Reference
<container::XIndexAccess
> xMembersIA( new ScNameToIndexAccess(xMembersNA
) );
622 sal_Int32 nCount
= xMembersIA
->getCount();
623 vector
<ScDPLabelData::Member
> aMembers
;
624 aMembers
.reserve(nCount
);
626 for (sal_Int32 i
= 0; i
< nCount
; ++i
)
628 Reference
<container::XNamed
> xMember(xMembersIA
->getByIndex(i
), UNO_QUERY
);
629 ScDPLabelData::Member aMem
;
632 aMem
.maName
= xMember
->getName();
634 Reference
<beans::XPropertySet
> xMemProp(xMember
, UNO_QUERY
);
637 aMem
.mbVisible
= ScUnoHelpFunctions::GetBoolProperty(xMemProp
, OUString::createFromAscii(SC_UNO_ISVISIBL
));
638 aMem
.mbShowDetails
= ScUnoHelpFunctions::GetBoolProperty(xMemProp
, OUString::createFromAscii(SC_UNO_SHOWDETA
));
640 aMem
.maLayoutName
= ScUnoHelpFunctions::GetStringProperty(
641 xMemProp
, OUString::createFromAscii(SC_UNO_LAYOUTNAME
), OUString());
644 aMembers
.push_back(aMem
);
646 rMembers
.swap(aMembers
);
650 void ScDPObject::UpdateReference( UpdateRefMode eUpdateRefMode
,
651 const ScRange
& rRange
, SCsCOL nDx
, SCsROW nDy
, SCsTAB nDz
)
655 SCCOL nCol1
= aOutRange
.aStart
.Col();
656 SCROW nRow1
= aOutRange
.aStart
.Row();
657 SCTAB nTab1
= aOutRange
.aStart
.Tab();
658 SCCOL nCol2
= aOutRange
.aEnd
.Col();
659 SCROW nRow2
= aOutRange
.aEnd
.Row();
660 SCTAB nTab2
= aOutRange
.aEnd
.Tab();
662 ScRefUpdateRes eRes
=
663 ScRefUpdate::Update( pDoc
, eUpdateRefMode
,
664 rRange
.aStart
.Col(), rRange
.aStart
.Row(), rRange
.aStart
.Tab(),
665 rRange
.aEnd
.Col(), rRange
.aEnd
.Row(), rRange
.aEnd
.Tab(), nDx
, nDy
, nDz
,
666 nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
);
667 if ( eRes
!= UR_NOTHING
)
668 SetOutRange( ScRange( nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
) );
674 nCol1
= pSheetDesc
->aSourceRange
.aStart
.Col();
675 nRow1
= pSheetDesc
->aSourceRange
.aStart
.Row();
676 nTab1
= pSheetDesc
->aSourceRange
.aStart
.Tab();
677 nCol2
= pSheetDesc
->aSourceRange
.aEnd
.Col();
678 nRow2
= pSheetDesc
->aSourceRange
.aEnd
.Row();
679 nTab2
= pSheetDesc
->aSourceRange
.aEnd
.Tab();
681 eRes
= ScRefUpdate::Update( pDoc
, eUpdateRefMode
,
682 rRange
.aStart
.Col(), rRange
.aStart
.Row(), rRange
.aStart
.Tab(),
683 rRange
.aEnd
.Col(), rRange
.aEnd
.Row(), rRange
.aEnd
.Tab(), nDx
, nDy
, nDz
,
684 nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
);
685 if ( eRes
!= UR_NOTHING
)
687 ScSheetSourceDesc aNewDesc
;
688 aNewDesc
.aSourceRange
= ScRange( nCol1
, nRow1
, nTab1
, nCol2
, nRow2
, nTab2
);
690 SCsCOL nDiffX
= nCol1
- (SCsCOL
) pSheetDesc
->aSourceRange
.aStart
.Col();
691 SCsROW nDiffY
= nRow1
- (SCsROW
) pSheetDesc
->aSourceRange
.aStart
.Row();
693 aNewDesc
.aQueryParam
= pSheetDesc
->aQueryParam
;
694 aNewDesc
.aQueryParam
.nCol1
= sal::static_int_cast
<SCCOL
>( aNewDesc
.aQueryParam
.nCol1
+ nDiffX
);
695 aNewDesc
.aQueryParam
.nCol2
= sal::static_int_cast
<SCCOL
>( aNewDesc
.aQueryParam
.nCol2
+ nDiffX
);
696 aNewDesc
.aQueryParam
.nRow1
+= nDiffY
; //! used?
697 aNewDesc
.aQueryParam
.nRow2
+= nDiffY
; //! used?
698 SCSIZE nEC
= aNewDesc
.aQueryParam
.GetEntryCount();
699 for (SCSIZE i
=0; i
<nEC
; i
++)
700 if (aNewDesc
.aQueryParam
.GetEntry(i
).bDoQuery
)
701 aNewDesc
.aQueryParam
.GetEntry(i
).nField
+= nDiffX
;
703 SetSheetDesc( aNewDesc
); // allocates new pSheetDesc
708 BOOL
ScDPObject::RefsEqual( const ScDPObject
& r
) const
710 if ( aOutRange
!= r
.aOutRange
)
713 if ( pSheetDesc
&& r
.pSheetDesc
)
715 if ( pSheetDesc
->aSourceRange
!= r
.pSheetDesc
->aSourceRange
)
718 else if ( pSheetDesc
|| r
.pSheetDesc
)
720 DBG_ERROR("RefsEqual: SheetDesc set at only one object");
727 void ScDPObject::WriteRefsTo( ScDPObject
& r
) const
729 r
.SetOutRange( aOutRange
);
731 r
.SetSheetDesc( *pSheetDesc
);
734 void ScDPObject::GetPositionData(const ScAddress
& rPos
, DataPilotTablePositionData
& rPosData
)
737 pOutput
->GetPositionData(rPos
, rPosData
);
740 bool ScDPObject::GetDataFieldPositionData(
741 const ScAddress
& rPos
, Sequence
<sheet::DataPilotFieldFilter
>& rFilters
)
745 vector
<sheet::DataPilotFieldFilter
> aFilters
;
746 if (!pOutput
->GetDataResultPositionData(aFilters
, rPos
))
749 sal_Int32 n
= static_cast<sal_Int32
>(aFilters
.size());
751 for (sal_Int32 i
= 0; i
< n
; ++i
)
752 rFilters
[i
] = aFilters
[i
];
757 void ScDPObject::GetDrillDownData(const ScAddress
& rPos
, Sequence
< Sequence
<Any
> >& rTableData
)
761 Reference
<sheet::XDrillDownDataSupplier
> xDrillDownData(xSource
, UNO_QUERY
);
762 if (!xDrillDownData
.is())
765 Sequence
<sheet::DataPilotFieldFilter
> filters
;
766 if (!GetDataFieldPositionData(rPos
, filters
))
769 rTableData
= xDrillDownData
->getDrillDownData(filters
);
772 bool ScDPObject::IsDimNameInUse(const OUString
& rName
) const
777 Reference
<container::XNameAccess
> xDims
= xSource
->getDimensions();
778 Sequence
<OUString
> aDimNames
= xDims
->getElementNames();
779 sal_Int32 n
= aDimNames
.getLength();
780 for (sal_Int32 i
= 0; i
< n
; ++i
)
782 const OUString
& rDimName
= aDimNames
[i
];
783 if (rDimName
.equalsIgnoreAsciiCase(rName
))
786 Reference
<beans::XPropertySet
> xPropSet(xDims
->getByName(rDimName
), UNO_QUERY
);
790 Any any
= xPropSet
->getPropertyValue(OUString::createFromAscii(SC_UNO_LAYOUTNAME
));
791 OUString aLayoutName
;
792 if (any
>>= aLayoutName
)
794 if (aLayoutName
.equalsIgnoreAsciiCase(rName
))
801 String
ScDPObject::GetDimName( long nDim
, BOOL
& rIsDataLayout
)
803 rIsDataLayout
= FALSE
;
808 uno::Reference
<container::XNameAccess
> xDimsName
= xSource
->getDimensions();
809 uno::Reference
<container::XIndexAccess
> xDims
= new ScNameToIndexAccess( xDimsName
);
810 long nDimCount
= xDims
->getCount();
811 if ( nDim
< nDimCount
)
813 uno::Reference
<uno::XInterface
> xIntDim
=
814 ScUnoHelpFunctions::AnyToInterface( xDims
->getByIndex(nDim
) );
815 uno::Reference
<container::XNamed
> xDimName( xIntDim
, uno::UNO_QUERY
);
816 uno::Reference
<beans::XPropertySet
> xDimProp( xIntDim
, uno::UNO_QUERY
);
817 if ( xDimName
.is() && xDimProp
.is() )
819 BOOL bData
= ScUnoHelpFunctions::GetBoolProperty( xDimProp
,
820 rtl::OUString::createFromAscii(DP_PROP_ISDATALAYOUT
) );
821 //! error checking -- is "IsDataLayoutDimension" property required??
826 aName
= xDimName
->getName();
828 catch(uno::Exception
&)
832 rIsDataLayout
= TRUE
;
834 aRet
= String( aName
);
842 BOOL
ScDPObject::IsDuplicated( long nDim
)
844 BOOL bDuplicated
= FALSE
;
847 uno::Reference
<container::XNameAccess
> xDimsName
= xSource
->getDimensions();
848 uno::Reference
<container::XIndexAccess
> xDims
= new ScNameToIndexAccess( xDimsName
);
849 long nDimCount
= xDims
->getCount();
850 if ( nDim
< nDimCount
)
852 uno::Reference
<uno::XInterface
> xIntDim
=
853 ScUnoHelpFunctions::AnyToInterface( xDims
->getByIndex(nDim
) );
854 uno::Reference
<beans::XPropertySet
> xDimProp( xIntDim
, uno::UNO_QUERY
);
859 uno::Any aOrigAny
= xDimProp
->getPropertyValue(
860 rtl::OUString::createFromAscii(DP_PROP_ORIGINAL
) );
861 uno::Reference
<uno::XInterface
> xIntOrig
;
862 if ( (aOrigAny
>>= xIntOrig
) && xIntOrig
.is() )
865 catch(uno::Exception
&)
874 long ScDPObject::GetDimCount()
881 uno::Reference
<container::XNameAccess
> xDimsName
= xSource
->getDimensions();
882 if ( xDimsName
.is() )
883 nRet
= xDimsName
->getElementNames().getLength();
885 catch(uno::Exception
&)
892 void ScDPObject::FillPageList( TypedScStrCollection
& rStrings
, long nField
)
894 //! merge members access with ToggleDetails?
896 //! convert field index to dimension index?
898 DBG_ASSERT( xSource
.is(), "no source" );
899 if ( !xSource
.is() ) return;
901 uno::Reference
<container::XNamed
> xDim
;
902 uno::Reference
<container::XNameAccess
> xDimsName
= xSource
->getDimensions();
903 uno::Reference
<container::XIndexAccess
> xIntDims
= new ScNameToIndexAccess( xDimsName
);
904 long nIntCount
= xIntDims
->getCount();
905 if ( nField
< nIntCount
)
907 uno::Reference
<uno::XInterface
> xIntDim
= ScUnoHelpFunctions::AnyToInterface(
908 xIntDims
->getByIndex(nField
) );
909 xDim
= uno::Reference
<container::XNamed
>( xIntDim
, uno::UNO_QUERY
);
911 DBG_ASSERT( xDim
.is(), "dimension not found" );
912 if ( !xDim
.is() ) return;
914 uno::Reference
<beans::XPropertySet
> xDimProp( xDim
, uno::UNO_QUERY
);
915 long nHierarchy
= ScUnoHelpFunctions::GetLongProperty( xDimProp
,
916 rtl::OUString::createFromAscii(DP_PROP_USEDHIERARCHY
) );
920 uno::Reference
<container::XIndexAccess
> xHiers
;
921 uno::Reference
<sheet::XHierarchiesSupplier
> xHierSupp( xDim
, uno::UNO_QUERY
);
922 if ( xHierSupp
.is() )
924 uno::Reference
<container::XNameAccess
> xHiersName
= xHierSupp
->getHierarchies();
925 xHiers
= new ScNameToIndexAccess( xHiersName
);
926 nHierCount
= xHiers
->getCount();
928 uno::Reference
<uno::XInterface
> xHier
;
929 if ( nHierarchy
< nHierCount
)
930 xHier
= ScUnoHelpFunctions::AnyToInterface( xHiers
->getByIndex(nHierarchy
) );
931 DBG_ASSERT( xHier
.is(), "hierarchy not found" );
932 if ( !xHier
.is() ) return;
935 uno::Reference
<container::XIndexAccess
> xLevels
;
936 uno::Reference
<sheet::XLevelsSupplier
> xLevSupp( xHier
, uno::UNO_QUERY
);
939 uno::Reference
<container::XNameAccess
> xLevsName
= xLevSupp
->getLevels();
940 xLevels
= new ScNameToIndexAccess( xLevsName
);
941 nLevCount
= xLevels
->getCount();
943 uno::Reference
<uno::XInterface
> xLevel
;
944 if ( nLevel
< nLevCount
)
945 xLevel
= ScUnoHelpFunctions::AnyToInterface( xLevels
->getByIndex(nLevel
) );
946 DBG_ASSERT( xLevel
.is(), "level not found" );
947 if ( !xLevel
.is() ) return;
949 uno::Reference
<container::XNameAccess
> xMembers
;
950 uno::Reference
<sheet::XMembersSupplier
> xMbrSupp( xLevel
, uno::UNO_QUERY
);
952 xMembers
= xMbrSupp
->getMembers();
953 DBG_ASSERT( xMembers
.is(), "members not found" );
954 if ( !xMembers
.is() ) return;
956 uno::Sequence
<rtl::OUString
> aNames
= xMembers
->getElementNames();
957 long nNameCount
= aNames
.getLength();
958 const rtl::OUString
* pNameArr
= aNames
.getConstArray();
959 for (long nPos
= 0; nPos
< nNameCount
; ++nPos
)
961 // Make sure to insert only visible members.
962 Reference
<XPropertySet
> xPropSet(xMembers
->getByName(pNameArr
[nPos
]), UNO_QUERY
);
963 sal_Bool bVisible
= false;
966 Any any
= xPropSet
->getPropertyValue(OUString::createFromAscii(SC_UNO_ISVISIBL
));
972 // use the order from getElementNames
973 TypedStrData
* pData
= new TypedStrData( pNameArr
[nPos
] );
974 if ( !rStrings
.AtInsert( rStrings
.GetCount(), pData
) )
979 // add "-all-" entry to the top (unsorted)
980 TypedStrData
* pAllData
= new TypedStrData( String( ScResId( SCSTR_ALL
) ) ); //! separate string? (also output)
981 if ( !rStrings
.AtInsert( 0, pAllData
) )
985 void ScDPObject::GetHeaderPositionData(const ScAddress
& rPos
, DataPilotTableHeaderData
& rData
)
987 using namespace ::com::sun::star::sheet::DataPilotTablePositionType
;
989 CreateOutput(); // create xSource and pOutput if not already done
991 // Reset member values to invalid state.
992 rData
.Dimension
= rData
.Hierarchy
= rData
.Level
= -1;
995 DataPilotTablePositionData aPosData
;
996 pOutput
->GetPositionData(rPos
, aPosData
);
997 const sal_Int32 nPosType
= aPosData
.PositionType
;
998 if (nPosType
== COLUMN_HEADER
|| nPosType
== ROW_HEADER
)
999 aPosData
.PositionData
>>= rData
;
1002 // Returns TRUE on success and stores the result in rTarget
1003 BOOL
ScDPObject::GetPivotData( ScDPGetPivotDataField
& rTarget
,
1004 const std::vector
< ScDPGetPivotDataField
>& rFilters
)
1006 CreateOutput(); // create xSource and pOutput if not already done
1008 return pOutput
->GetPivotData( rTarget
, rFilters
);
1011 BOOL
ScDPObject::IsFilterButton( const ScAddress
& rPos
)
1013 CreateOutput(); // create xSource and pOutput if not already done
1015 return pOutput
->IsFilterButton( rPos
);
1018 long ScDPObject::GetHeaderDim( const ScAddress
& rPos
, USHORT
& rOrient
)
1020 CreateOutput(); // create xSource and pOutput if not already done
1022 return pOutput
->GetHeaderDim( rPos
, rOrient
);
1025 BOOL
ScDPObject::GetHeaderDrag( const ScAddress
& rPos
, BOOL bMouseLeft
, BOOL bMouseTop
, long nDragDim
,
1026 Rectangle
& rPosRect
, USHORT
& rOrient
, long& rDimPos
)
1028 CreateOutput(); // create xSource and pOutput if not already done
1030 return pOutput
->GetHeaderDrag( rPos
, bMouseLeft
, bMouseTop
, nDragDim
, rPosRect
, rOrient
, rDimPos
);
1033 void ScDPObject::GetMemberResultNames( ScStrCollection
& rNames
, long nDimension
)
1035 CreateOutput(); // create xSource and pOutput if not already done
1037 pOutput
->GetMemberResultNames( rNames
, nDimension
); // used only with table data -> level not needed
1040 bool lcl_Dequote( const String
& rSource
, xub_StrLen nStartPos
, xub_StrLen
& rEndPos
, String
& rResult
)
1042 // nStartPos has to point to opening quote
1045 const sal_Unicode cQuote
= '\'';
1047 if ( rSource
.GetChar(nStartPos
) == cQuote
)
1049 rtl::OUStringBuffer aBuffer
;
1050 xub_StrLen nPos
= nStartPos
+ 1;
1051 const xub_StrLen nLen
= rSource
.Len();
1053 while ( nPos
< nLen
)
1055 const sal_Unicode cNext
= rSource
.GetChar(nPos
);
1056 if ( cNext
== cQuote
)
1058 if ( nPos
+1 < nLen
&& rSource
.GetChar(nPos
+1) == cQuote
)
1060 // double quote is used for an embedded quote
1061 aBuffer
.append( cNext
); // append one quote
1062 ++nPos
; // skip the next one
1066 // end of quoted string
1067 rResult
= aBuffer
.makeStringAndClear();
1068 rEndPos
= nPos
+ 1; // behind closing quote
1073 aBuffer
.append( cNext
);
1077 // no closing quote before the end of the string -> error (bRet still false)
1083 struct ScGetPivotDataFunctionEntry
1085 const sal_Char
* pName
;
1086 sheet::GeneralFunction eFunc
;
1089 bool lcl_ParseFunction( const String
& rList
, xub_StrLen nStartPos
, xub_StrLen
& rEndPos
, sheet::GeneralFunction
& rFunc
)
1091 static const ScGetPivotDataFunctionEntry aFunctions
[] =
1094 { "Sum", sheet::GeneralFunction_SUM
},
1095 { "Count", sheet::GeneralFunction_COUNT
},
1096 { "Average", sheet::GeneralFunction_AVERAGE
},
1097 { "Max", sheet::GeneralFunction_MAX
},
1098 { "Min", sheet::GeneralFunction_MIN
},
1099 { "Product", sheet::GeneralFunction_PRODUCT
},
1100 { "CountNums", sheet::GeneralFunction_COUNTNUMS
},
1101 { "StDev", sheet::GeneralFunction_STDEV
},
1102 { "StDevp", sheet::GeneralFunction_STDEVP
},
1103 { "Var", sheet::GeneralFunction_VAR
},
1104 { "VarP", sheet::GeneralFunction_VARP
},
1105 // compatibility names
1106 { "Count Nums", sheet::GeneralFunction_COUNTNUMS
},
1107 { "StdDev", sheet::GeneralFunction_STDEV
},
1108 { "StdDevp", sheet::GeneralFunction_STDEVP
}
1111 const xub_StrLen nListLen
= rList
.Len();
1112 while ( nStartPos
< nListLen
&& rList
.GetChar(nStartPos
) == ' ' )
1115 bool bParsed
= false;
1116 bool bFound
= false;
1118 xub_StrLen nFuncEnd
= 0;
1119 if ( nStartPos
< nListLen
&& rList
.GetChar(nStartPos
) == '\'' )
1120 bParsed
= lcl_Dequote( rList
, nStartPos
, nFuncEnd
, aFuncStr
);
1123 nFuncEnd
= rList
.Search( static_cast<sal_Unicode
>(']'), nStartPos
);
1124 if ( nFuncEnd
!= STRING_NOTFOUND
)
1126 aFuncStr
= rList
.Copy( nStartPos
, nFuncEnd
- nStartPos
);
1133 aFuncStr
.EraseLeadingAndTrailingChars( ' ' );
1135 const sal_Int32 nFuncCount
= sizeof(aFunctions
) / sizeof(aFunctions
[0]);
1136 for ( sal_Int32 nFunc
=0; nFunc
<nFuncCount
&& !bFound
; nFunc
++ )
1138 if ( aFuncStr
.EqualsIgnoreCaseAscii( aFunctions
[nFunc
].pName
) )
1140 rFunc
= aFunctions
[nFunc
].eFunc
;
1143 while ( nFuncEnd
< nListLen
&& rList
.GetChar(nFuncEnd
) == ' ' )
1153 bool lcl_IsAtStart( const String
& rList
, const String
& rSearch
, sal_Int32
& rMatched
,
1154 bool bAllowBracket
, sheet::GeneralFunction
* pFunc
)
1156 sal_Int32 nMatchList
= 0;
1157 sal_Int32 nMatchSearch
= 0;
1158 sal_Unicode cFirst
= rList
.GetChar(0);
1159 if ( cFirst
== '\'' || cFirst
== '[' )
1161 // quoted string or string in brackets must match completely
1164 xub_StrLen nQuoteEnd
= 0;
1165 bool bParsed
= false;
1167 if ( cFirst
== '\'' )
1168 bParsed
= lcl_Dequote( rList
, 0, nQuoteEnd
, aDequoted
);
1169 else if ( cFirst
== '[' )
1171 // skip spaces after the opening bracket
1173 xub_StrLen nStartPos
= 1;
1174 const xub_StrLen nListLen
= rList
.Len();
1175 while ( nStartPos
< nListLen
&& rList
.GetChar(nStartPos
) == ' ' )
1178 if ( rList
.GetChar(nStartPos
) == '\'' ) // quoted within the brackets?
1180 if ( lcl_Dequote( rList
, nStartPos
, nQuoteEnd
, aDequoted
) )
1182 // after the quoted string, there must be the closing bracket, optionally preceded by spaces,
1183 // and/or a function name
1184 while ( nQuoteEnd
< nListLen
&& rList
.GetChar(nQuoteEnd
) == ' ' )
1187 // semicolon separates function name
1188 if ( nQuoteEnd
< nListLen
&& rList
.GetChar(nQuoteEnd
) == ';' && pFunc
)
1190 xub_StrLen nFuncEnd
= 0;
1191 if ( lcl_ParseFunction( rList
, nQuoteEnd
+ 1, nFuncEnd
, *pFunc
) )
1192 nQuoteEnd
= nFuncEnd
;
1194 if ( nQuoteEnd
< nListLen
&& rList
.GetChar(nQuoteEnd
) == ']' )
1196 ++nQuoteEnd
; // include the closing bracket for the matched length
1203 // implicit quoting to the closing bracket
1205 xub_StrLen nClosePos
= rList
.Search( static_cast<sal_Unicode
>(']'), nStartPos
);
1206 if ( nClosePos
!= STRING_NOTFOUND
)
1208 xub_StrLen nNameEnd
= nClosePos
;
1209 xub_StrLen nSemiPos
= rList
.Search( static_cast<sal_Unicode
>(';'), nStartPos
);
1210 if ( nSemiPos
!= STRING_NOTFOUND
&& nSemiPos
< nClosePos
&& pFunc
)
1212 xub_StrLen nFuncEnd
= 0;
1213 if ( lcl_ParseFunction( rList
, nSemiPos
+ 1, nFuncEnd
, *pFunc
) )
1214 nNameEnd
= nSemiPos
;
1217 aDequoted
= rList
.Copy( nStartPos
, nNameEnd
- nStartPos
);
1218 aDequoted
.EraseTrailingChars( ' ' ); // spaces before the closing bracket or semicolon
1219 nQuoteEnd
= nClosePos
+ 1;
1225 if ( bParsed
&& ScGlobal::GetpTransliteration()->isEqual( aDequoted
, rSearch
) )
1227 nMatchList
= nQuoteEnd
; // match count in the list string, including quotes
1228 nMatchSearch
= rSearch
.Len();
1233 // otherwise look for search string at the start of rList
1234 ScGlobal::GetpTransliteration()->equals( rList
, 0, rList
.Len(), nMatchList
,
1235 rSearch
, 0, rSearch
.Len(), nMatchSearch
);
1238 if ( nMatchSearch
== rSearch
.Len() )
1240 // search string is at start of rList - look for following space or end of string
1242 bool bValid
= false;
1243 if ( sal::static_int_cast
<xub_StrLen
>(nMatchList
) >= rList
.Len() )
1247 sal_Unicode cNext
= rList
.GetChar(sal::static_int_cast
<xub_StrLen
>(nMatchList
));
1248 if ( cNext
== ' ' || ( bAllowBracket
&& cNext
== '[' ) )
1254 rMatched
= nMatchList
;
1262 BOOL
ScDPObject::ParseFilters( ScDPGetPivotDataField
& rTarget
,
1263 std::vector
< ScDPGetPivotDataField
>& rFilters
,
1264 const String
& rFilterList
)
1266 // parse the string rFilterList into parameters for GetPivotData
1268 CreateObjects(); // create xSource if not already done
1270 std::vector
<String
> aDataNames
; // data fields (source name)
1271 std::vector
<String
> aGivenNames
; // data fields (compound name)
1272 std::vector
<String
> aFieldNames
; // column/row/data fields
1273 std::vector
< uno::Sequence
<rtl::OUString
> > aFieldValues
;
1276 // get all the field and item names
1279 uno::Reference
<container::XNameAccess
> xDimsName
= xSource
->getDimensions();
1280 uno::Reference
<container::XIndexAccess
> xIntDims
= new ScNameToIndexAccess( xDimsName
);
1281 sal_Int32 nDimCount
= xIntDims
->getCount();
1282 for ( sal_Int32 nDim
= 0; nDim
<nDimCount
; nDim
++ )
1284 uno::Reference
<uno::XInterface
> xIntDim
= ScUnoHelpFunctions::AnyToInterface( xIntDims
->getByIndex(nDim
) );
1285 uno::Reference
<container::XNamed
> xDim( xIntDim
, uno::UNO_QUERY
);
1286 uno::Reference
<beans::XPropertySet
> xDimProp( xDim
, uno::UNO_QUERY
);
1287 uno::Reference
<sheet::XHierarchiesSupplier
> xDimSupp( xDim
, uno::UNO_QUERY
);
1288 BOOL bDataLayout
= ScUnoHelpFunctions::GetBoolProperty( xDimProp
,
1289 rtl::OUString::createFromAscii(DP_PROP_ISDATALAYOUT
) );
1290 sal_Int32 nOrient
= ScUnoHelpFunctions::GetEnumProperty(
1291 xDimProp
, rtl::OUString::createFromAscii(DP_PROP_ORIENTATION
),
1292 sheet::DataPilotFieldOrientation_HIDDEN
);
1295 if ( nOrient
== sheet::DataPilotFieldOrientation_DATA
)
1299 ScDPOutput::GetDataDimensionNames( aSourceName
, aGivenName
, xIntDim
);
1300 aDataNames
.push_back( aSourceName
);
1301 aGivenNames
.push_back( aGivenName
);
1303 else if ( nOrient
!= sheet::DataPilotFieldOrientation_HIDDEN
)
1305 // get level names, as in ScDPOutput
1307 uno::Reference
<container::XIndexAccess
> xHiers
= new ScNameToIndexAccess( xDimSupp
->getHierarchies() );
1308 sal_Int32 nHierarchy
= ScUnoHelpFunctions::GetLongProperty( xDimProp
,
1309 rtl::OUString::createFromAscii(DP_PROP_USEDHIERARCHY
) );
1310 if ( nHierarchy
>= xHiers
->getCount() )
1313 uno::Reference
<uno::XInterface
> xHier
= ScUnoHelpFunctions::AnyToInterface(
1314 xHiers
->getByIndex(nHierarchy
) );
1315 uno::Reference
<sheet::XLevelsSupplier
> xHierSupp( xHier
, uno::UNO_QUERY
);
1316 if ( xHierSupp
.is() )
1318 uno::Reference
<container::XIndexAccess
> xLevels
= new ScNameToIndexAccess( xHierSupp
->getLevels() );
1319 sal_Int32 nLevCount
= xLevels
->getCount();
1320 for (sal_Int32 nLev
=0; nLev
<nLevCount
; nLev
++)
1322 uno::Reference
<uno::XInterface
> xLevel
= ScUnoHelpFunctions::AnyToInterface(
1323 xLevels
->getByIndex(nLev
) );
1324 uno::Reference
<container::XNamed
> xLevNam( xLevel
, uno::UNO_QUERY
);
1325 uno::Reference
<sheet::XMembersSupplier
> xLevSupp( xLevel
, uno::UNO_QUERY
);
1326 if ( xLevNam
.is() && xLevSupp
.is() )
1328 uno::Reference
<container::XNameAccess
> xMembers
= xLevSupp
->getMembers();
1330 String
aFieldName( xLevNam
->getName() );
1331 uno::Sequence
<rtl::OUString
> aMemberNames( xMembers
->getElementNames() );
1333 aFieldNames
.push_back( aFieldName
);
1334 aFieldValues
.push_back( aMemberNames
);
1343 // compare and build filters
1346 SCSIZE nDataFields
= aDataNames
.size();
1347 SCSIZE nFieldCount
= aFieldNames
.size();
1348 DBG_ASSERT( aGivenNames
.size() == nDataFields
&& aFieldValues
.size() == nFieldCount
, "wrong count" );
1350 bool bError
= false;
1351 bool bHasData
= false;
1352 String
aRemaining( rFilterList
);
1353 aRemaining
.EraseLeadingAndTrailingChars( ' ' );
1354 while ( aRemaining
.Len() && !bError
)
1358 // look for data field name
1360 for ( SCSIZE nDataPos
=0; nDataPos
<nDataFields
&& !bUsed
; nDataPos
++ )
1363 sal_Int32 nMatched
= 0;
1364 if ( lcl_IsAtStart( aRemaining
, aDataNames
[nDataPos
], nMatched
, false, NULL
) )
1365 aFound
= aDataNames
[nDataPos
];
1366 else if ( lcl_IsAtStart( aRemaining
, aGivenNames
[nDataPos
], nMatched
, false, NULL
) )
1367 aFound
= aGivenNames
[nDataPos
];
1371 rTarget
.maFieldName
= aFound
;
1372 aRemaining
.Erase( 0, sal::static_int_cast
<xub_StrLen
>(nMatched
) );
1378 // look for field name
1381 bool bHasFieldName
= false;
1384 sal_Int32 nMatched
= 0;
1385 for ( SCSIZE nField
=0; nField
<nFieldCount
&& !bHasFieldName
; nField
++ )
1387 if ( lcl_IsAtStart( aRemaining
, aFieldNames
[nField
], nMatched
, true, NULL
) )
1389 aSpecField
= aFieldNames
[nField
];
1390 aRemaining
.Erase( 0, sal::static_int_cast
<xub_StrLen
>(nMatched
) );
1391 aRemaining
.EraseLeadingChars( ' ' );
1393 // field name has to be followed by item name in brackets
1394 if ( aRemaining
.GetChar(0) == '[' )
1396 bHasFieldName
= true;
1397 // bUsed remains false - still need the item
1408 // look for field item
1412 bool bItemFound
= false;
1413 sal_Int32 nMatched
= 0;
1416 sheet::GeneralFunction eFunc
= sheet::GeneralFunction_NONE
;
1417 sheet::GeneralFunction eFoundFunc
= sheet::GeneralFunction_NONE
;
1419 for ( SCSIZE nField
=0; nField
<nFieldCount
; nField
++ )
1421 // If a field name is given, look in that field only, otherwise in all fields.
1422 // aSpecField is initialized from aFieldNames array, so exact comparison can be used.
1423 if ( !bHasFieldName
|| aFieldNames
[nField
] == aSpecField
)
1425 const uno::Sequence
<rtl::OUString
>& rItems
= aFieldValues
[nField
];
1426 sal_Int32 nItemCount
= rItems
.getLength();
1427 const rtl::OUString
* pItemArr
= rItems
.getConstArray();
1428 for ( sal_Int32 nItem
=0; nItem
<nItemCount
; nItem
++ )
1430 if ( lcl_IsAtStart( aRemaining
, pItemArr
[nItem
], nMatched
, false, &eFunc
) )
1433 bError
= true; // duplicate (also across fields)
1436 aFoundName
= aFieldNames
[nField
];
1437 aFoundValue
= pItemArr
[nItem
];
1447 if ( bItemFound
&& !bError
)
1449 ScDPGetPivotDataField aField
;
1450 aField
.maFieldName
= aFoundName
;
1451 aField
.meFunction
= eFoundFunc
;
1452 aField
.mbValIsStr
= true;
1453 aField
.maValStr
= aFoundValue
;
1454 aField
.mnValNum
= 0.0;
1455 rFilters
.push_back( aField
);
1457 aRemaining
.Erase( 0, sal::static_int_cast
<xub_StrLen
>(nMatched
) );
1464 aRemaining
.EraseLeadingChars( ' ' ); // remove any number of spaces between entries
1467 if ( !bError
&& !bHasData
&& aDataNames
.size() == 1 )
1469 // if there's only one data field, its name need not be specified
1470 rTarget
.maFieldName
= aDataNames
[0];
1474 return bHasData
&& !bError
;
1477 void ScDPObject::ToggleDetails(const DataPilotTableHeaderData
& rElemDesc
, ScDPObject
* pDestObj
)
1479 CreateObjects(); // create xSource if not already done
1481 // find dimension name
1483 uno::Reference
<container::XNamed
> xDim
;
1484 uno::Reference
<container::XNameAccess
> xDimsName
= xSource
->getDimensions();
1485 uno::Reference
<container::XIndexAccess
> xIntDims
= new ScNameToIndexAccess( xDimsName
);
1486 long nIntCount
= xIntDims
->getCount();
1487 if ( rElemDesc
.Dimension
< nIntCount
)
1489 uno::Reference
<uno::XInterface
> xIntDim
= ScUnoHelpFunctions::AnyToInterface(
1490 xIntDims
->getByIndex(rElemDesc
.Dimension
) );
1491 xDim
= uno::Reference
<container::XNamed
>( xIntDim
, uno::UNO_QUERY
);
1493 DBG_ASSERT( xDim
.is(), "dimension not found" );
1494 if ( !xDim
.is() ) return;
1495 String aDimName
= xDim
->getName();
1497 uno::Reference
<beans::XPropertySet
> xDimProp( xDim
, uno::UNO_QUERY
);
1498 BOOL bDataLayout
= ScUnoHelpFunctions::GetBoolProperty( xDimProp
,
1499 rtl::OUString::createFromAscii(DP_PROP_ISDATALAYOUT
) );
1502 // the elements of the data layout dimension can't be found by their names
1503 // -> don't change anything
1509 long nHierCount
= 0;
1510 uno::Reference
<container::XIndexAccess
> xHiers
;
1511 uno::Reference
<sheet::XHierarchiesSupplier
> xHierSupp( xDim
, uno::UNO_QUERY
);
1512 if ( xHierSupp
.is() )
1514 uno::Reference
<container::XNameAccess
> xHiersName
= xHierSupp
->getHierarchies();
1515 xHiers
= new ScNameToIndexAccess( xHiersName
);
1516 nHierCount
= xHiers
->getCount();
1518 uno::Reference
<uno::XInterface
> xHier
;
1519 if ( rElemDesc
.Hierarchy
< nHierCount
)
1520 xHier
= ScUnoHelpFunctions::AnyToInterface( xHiers
->getByIndex(rElemDesc
.Hierarchy
) );
1521 DBG_ASSERT( xHier
.is(), "hierarchy not found" );
1522 if ( !xHier
.is() ) return;
1525 uno::Reference
<container::XIndexAccess
> xLevels
;
1526 uno::Reference
<sheet::XLevelsSupplier
> xLevSupp( xHier
, uno::UNO_QUERY
);
1527 if ( xLevSupp
.is() )
1529 uno::Reference
<container::XNameAccess
> xLevsName
= xLevSupp
->getLevels();
1530 xLevels
= new ScNameToIndexAccess( xLevsName
);
1531 nLevCount
= xLevels
->getCount();
1533 uno::Reference
<uno::XInterface
> xLevel
;
1534 if ( rElemDesc
.Level
< nLevCount
)
1535 xLevel
= ScUnoHelpFunctions::AnyToInterface( xLevels
->getByIndex(rElemDesc
.Level
) );
1536 DBG_ASSERT( xLevel
.is(), "level not found" );
1537 if ( !xLevel
.is() ) return;
1539 uno::Reference
<container::XNameAccess
> xMembers
;
1540 uno::Reference
<sheet::XMembersSupplier
> xMbrSupp( xLevel
, uno::UNO_QUERY
);
1541 if ( xMbrSupp
.is() )
1542 xMembers
= xMbrSupp
->getMembers();
1544 BOOL bFound
= FALSE
;
1545 BOOL bShowDetails
= TRUE
;
1547 if ( xMembers
.is() )
1549 if ( xMembers
->hasByName(rElemDesc
.MemberName
) )
1551 uno::Reference
<uno::XInterface
> xMemberInt
= ScUnoHelpFunctions::AnyToInterface(
1552 xMembers
->getByName(rElemDesc
.MemberName
) );
1553 uno::Reference
<beans::XPropertySet
> xMbrProp( xMemberInt
, uno::UNO_QUERY
);
1554 if ( xMbrProp
.is() )
1556 bShowDetails
= ScUnoHelpFunctions::GetBoolProperty( xMbrProp
,
1557 rtl::OUString::createFromAscii(DP_PROP_SHOWDETAILS
) );
1558 //! don't set bFound if property is unknown?
1564 DBG_ASSERT( bFound
, "member not found" );
1566 //! use Hierarchy and Level in SaveData !!!!
1568 // modify pDestObj if set, this object otherwise
1569 ScDPSaveData
* pModifyData
= pDestObj
? ( pDestObj
->pSaveData
) : pSaveData
;
1570 DBG_ASSERT( pModifyData
, "no data?" );
1573 const String aName
= rElemDesc
.MemberName
;
1574 pModifyData
->GetDimensionByName(aDimName
)->
1575 GetMemberByName(aName
)->SetShowDetails( !bShowDetails
); // toggle
1578 pDestObj
->InvalidateData(); // re-init source from SaveData
1580 InvalidateData(); // re-init source from SaveData
1584 long lcl_FindName( const rtl::OUString
& rString
, const uno::Reference
<container::XNameAccess
>& xCollection
)
1586 if ( xCollection
.is() )
1588 uno::Sequence
<rtl::OUString
> aSeq
= xCollection
->getElementNames();
1589 long nCount
= aSeq
.getLength();
1590 const rtl::OUString
* pArr
= aSeq
.getConstArray();
1591 for (long nPos
=0; nPos
<nCount
; nPos
++)
1592 if ( pArr
[nPos
] == rString
)
1595 return -1; // not found
1598 USHORT
lcl_FirstSubTotal( const uno::Reference
<beans::XPropertySet
>& xDimProp
) // PIVOT_FUNC mask
1600 uno::Reference
<sheet::XHierarchiesSupplier
> xDimSupp( xDimProp
, uno::UNO_QUERY
);
1601 if ( xDimProp
.is() && xDimSupp
.is() )
1603 uno::Reference
<container::XIndexAccess
> xHiers
= new ScNameToIndexAccess( xDimSupp
->getHierarchies() );
1604 long nHierarchy
= ScUnoHelpFunctions::GetLongProperty( xDimProp
,
1605 rtl::OUString::createFromAscii(DP_PROP_USEDHIERARCHY
) );
1606 if ( nHierarchy
>= xHiers
->getCount() )
1609 uno::Reference
<uno::XInterface
> xHier
= ScUnoHelpFunctions::AnyToInterface(
1610 xHiers
->getByIndex(nHierarchy
) );
1611 uno::Reference
<sheet::XLevelsSupplier
> xHierSupp( xHier
, uno::UNO_QUERY
);
1612 if ( xHierSupp
.is() )
1614 uno::Reference
<container::XIndexAccess
> xLevels
= new ScNameToIndexAccess( xHierSupp
->getLevels() );
1615 uno::Reference
<uno::XInterface
> xLevel
=
1616 ScUnoHelpFunctions::AnyToInterface( xLevels
->getByIndex( 0 ) );
1617 uno::Reference
<beans::XPropertySet
> xLevProp( xLevel
, uno::UNO_QUERY
);
1618 if ( xLevProp
.is() )
1623 aSubAny
= xLevProp
->getPropertyValue(
1624 rtl::OUString::createFromAscii(DP_PROP_SUBTOTALS
) );
1626 catch(uno::Exception
&)
1629 uno::Sequence
<sheet::GeneralFunction
> aSeq
;
1630 if ( aSubAny
>>= aSeq
)
1633 const sheet::GeneralFunction
* pArray
= aSeq
.getConstArray();
1634 long nCount
= aSeq
.getLength();
1635 for (long i
=0; i
<nCount
; i
++)
1636 nMask
|= ScDataPilotConversion::FunctionBit(pArray
[i
]);
1643 DBG_ERROR("FirstSubTotal: NULL");
1647 USHORT
lcl_CountBits( USHORT nBits
)
1649 if (!nBits
) return 0;
1653 for (USHORT i
=0; i
<16; i
++)
1655 if ( nBits
& nMask
)
1662 SCSIZE
lcl_FillOldFields( PivotField
* pFields
,
1663 const uno::Reference
<sheet::XDimensionsSupplier
>& xSource
,
1664 USHORT nOrient
, SCCOL nColAdd
, BOOL bAddData
)
1666 SCSIZE nOutCount
= 0;
1667 BOOL bDataFound
= FALSE
;
1669 SCSIZE nCount
= (nOrient
== sheet::DataPilotFieldOrientation_PAGE
) ? PIVOT_MAXPAGEFIELD
: PIVOT_MAXFIELD
;
1671 //! merge multiple occurences (data field with different functions)
1672 //! force data field in one dimension
1674 std::vector
< long > aPos( nCount
, 0 );
1676 uno::Reference
<container::XNameAccess
> xDimsName
= xSource
->getDimensions();
1677 uno::Reference
<container::XIndexAccess
> xDims
= new ScNameToIndexAccess( xDimsName
);
1678 long nDimCount
= xDims
->getCount();
1679 for (long nDim
=0; nDim
< nDimCount
&& nOutCount
< nCount
; nDim
++)
1681 uno::Reference
<uno::XInterface
> xIntDim
=
1682 ScUnoHelpFunctions::AnyToInterface( xDims
->getByIndex(nDim
) );
1683 uno::Reference
<beans::XPropertySet
> xDimProp( xIntDim
, uno::UNO_QUERY
);
1684 long nDimOrient
= ScUnoHelpFunctions::GetEnumProperty(
1685 xDimProp
, rtl::OUString::createFromAscii(DP_PROP_ORIENTATION
),
1686 sheet::DataPilotFieldOrientation_HIDDEN
);
1687 if ( xDimProp
.is() && nDimOrient
== nOrient
)
1690 if ( nOrient
== sheet::DataPilotFieldOrientation_DATA
)
1692 sheet::GeneralFunction eFunc
= (sheet::GeneralFunction
)ScUnoHelpFunctions::GetEnumProperty(
1693 xDimProp
, rtl::OUString::createFromAscii(DP_PROP_FUNCTION
),
1694 sheet::GeneralFunction_NONE
);
1695 if ( eFunc
== sheet::GeneralFunction_AUTO
)
1697 //! test for numeric data
1698 eFunc
= sheet::GeneralFunction_SUM
;
1700 nMask
= ScDataPilotConversion::FunctionBit(eFunc
);
1703 nMask
= lcl_FirstSubTotal( xDimProp
); // from first hierarchy
1705 BOOL bDataLayout
= ScUnoHelpFunctions::GetBoolProperty( xDimProp
,
1706 rtl::OUString::createFromAscii(DP_PROP_ISDATALAYOUT
) );
1710 aOrigAny
= xDimProp
->getPropertyValue(
1711 rtl::OUString::createFromAscii(DP_PROP_ORIGINAL
) );
1713 catch(uno::Exception
&)
1717 long nDupSource
= -1;
1718 uno::Reference
<uno::XInterface
> xIntOrig
= ScUnoHelpFunctions::AnyToInterface( aOrigAny
);
1719 if ( xIntOrig
.is() )
1721 uno::Reference
<container::XNamed
> xNameOrig( xIntOrig
, uno::UNO_QUERY
);
1722 if ( xNameOrig
.is() )
1723 nDupSource
= lcl_FindName( xNameOrig
->getName(), xDimsName
);
1726 BOOL bDupUsed
= FALSE
;
1727 if ( nDupSource
>= 0 )
1729 // add function bit to previous entry
1733 nCompCol
= PIVOT_DATA_FIELD
;
1735 nCompCol
= static_cast<SCsCOL
>(nDupSource
)+nColAdd
; //! seek source column from name
1737 for (SCSIZE nOld
=0; nOld
<nOutCount
&& !bDupUsed
; nOld
++)
1738 if ( pFields
[nOld
].nCol
== nCompCol
)
1740 // add to previous column only if new bits aren't already set there
1741 if ( ( pFields
[nOld
].nFuncMask
& nMask
) == 0 )
1743 pFields
[nOld
].nFuncMask
|= nMask
;
1744 pFields
[nOld
].nFuncCount
= lcl_CountBits( pFields
[nOld
].nFuncMask
);
1750 if ( !bDupUsed
) // also for duplicated dim if original has different orientation
1754 pFields
[nOutCount
].nCol
= PIVOT_DATA_FIELD
;
1757 else if ( nDupSource
>= 0 ) // if source was not found (different orientation)
1758 pFields
[nOutCount
].nCol
= static_cast<SCsCOL
>(nDupSource
)+nColAdd
; //! seek from name
1760 pFields
[nOutCount
].nCol
= static_cast<SCsCOL
>(nDim
)+nColAdd
; //! seek source column from name
1762 pFields
[nOutCount
].nFuncMask
= nMask
;
1763 pFields
[nOutCount
].nFuncCount
= lcl_CountBits( nMask
);
1764 aPos
[nOutCount
] = ScUnoHelpFunctions::GetLongProperty( xDimProp
,
1765 rtl::OUString::createFromAscii(DP_PROP_POSITION
) );
1769 if( nOrient
== sheet::DataPilotFieldOrientation_DATA
)
1770 xDimProp
->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNO_REFVALUE
) ) )
1771 >>= pFields
[nOutCount
].maFieldRef
;
1773 catch( uno::Exception
& )
1782 // sort by getPosition() value
1784 for (SCSIZE i
=0; i
+1<nOutCount
; i
++)
1786 for (SCSIZE j
=0; j
+i
+1<nOutCount
; j
++)
1787 if ( aPos
[j
+1] < aPos
[j
] )
1789 std::swap( aPos
[j
], aPos
[j
+1] );
1790 std::swap( pFields
[j
], pFields
[j
+1] );
1794 if ( bAddData
&& !bDataFound
)
1796 if ( nOutCount
>= nCount
) // space for data field?
1797 --nOutCount
; //! error?
1798 pFields
[nOutCount
].nCol
= PIVOT_DATA_FIELD
;
1799 pFields
[nOutCount
].nFuncMask
= 0;
1800 pFields
[nOutCount
].nFuncCount
= 0;
1807 BOOL
ScDPObject::FillOldParam(ScPivotParam
& rParam
, BOOL bForFile
) const
1809 ((ScDPObject
*)this)->CreateObjects(); // xSource is needed for field numbers
1811 rParam
.nCol
= aOutRange
.aStart
.Col();
1812 rParam
.nRow
= aOutRange
.aStart
.Row();
1813 rParam
.nTab
= aOutRange
.aStart
.Tab();
1814 // ppLabelArr / nLabels is not changed
1819 // in old file format, columns are within document, not within source range
1821 DBG_ASSERT( pSheetDesc
, "FillOldParam: bForFile, !pSheetDesc" );
1822 nColAdd
= pSheetDesc
->aSourceRange
.aStart
.Col();
1825 BOOL bAddData
= ( lcl_GetDataGetOrientation( xSource
) == sheet::DataPilotFieldOrientation_HIDDEN
);
1826 rParam
.nPageCount
= lcl_FillOldFields( rParam
.aPageArr
,
1827 xSource
, sheet::DataPilotFieldOrientation_PAGE
, nColAdd
, FALSE
);
1828 rParam
.nColCount
= lcl_FillOldFields( rParam
.aColArr
,
1829 xSource
, sheet::DataPilotFieldOrientation_COLUMN
, nColAdd
, bAddData
);
1830 rParam
.nRowCount
= lcl_FillOldFields( rParam
.aRowArr
,
1831 xSource
, sheet::DataPilotFieldOrientation_ROW
, nColAdd
, FALSE
);
1832 rParam
.nDataCount
= lcl_FillOldFields( rParam
.aDataArr
,
1833 xSource
, sheet::DataPilotFieldOrientation_DATA
, nColAdd
, FALSE
);
1835 uno::Reference
<beans::XPropertySet
> xProp( xSource
, uno::UNO_QUERY
);
1840 rParam
.bMakeTotalCol
= ScUnoHelpFunctions::GetBoolProperty( xProp
,
1841 rtl::OUString::createFromAscii(DP_PROP_COLUMNGRAND
), TRUE
);
1842 rParam
.bMakeTotalRow
= ScUnoHelpFunctions::GetBoolProperty( xProp
,
1843 rtl::OUString::createFromAscii(DP_PROP_ROWGRAND
), TRUE
);
1845 // following properties may be missing for external sources
1846 rParam
.bIgnoreEmptyRows
= ScUnoHelpFunctions::GetBoolProperty( xProp
,
1847 rtl::OUString::createFromAscii(DP_PROP_IGNOREEMPTY
) );
1848 rParam
.bDetectCategories
= ScUnoHelpFunctions::GetBoolProperty( xProp
,
1849 rtl::OUString::createFromAscii(DP_PROP_REPEATIFEMPTY
) );
1851 catch(uno::Exception
&)
1859 void lcl_FillLabelData( ScDPLabelData
& rData
, const uno::Reference
< beans::XPropertySet
>& xDimProp
)
1861 uno::Reference
<sheet::XHierarchiesSupplier
> xDimSupp( xDimProp
, uno::UNO_QUERY
);
1862 if ( xDimProp
.is() && xDimSupp
.is() )
1864 uno::Reference
<container::XIndexAccess
> xHiers
= new ScNameToIndexAccess( xDimSupp
->getHierarchies() );
1865 long nHierarchy
= ScUnoHelpFunctions::GetLongProperty( xDimProp
,
1866 rtl::OUString::createFromAscii(DP_PROP_USEDHIERARCHY
) );
1867 if ( nHierarchy
>= xHiers
->getCount() )
1869 rData
.mnUsedHier
= nHierarchy
;
1871 uno::Reference
<uno::XInterface
> xHier
= ScUnoHelpFunctions::AnyToInterface(
1872 xHiers
->getByIndex(nHierarchy
) );
1874 uno::Reference
<sheet::XLevelsSupplier
> xHierSupp( xHier
, uno::UNO_QUERY
);
1875 if ( xHierSupp
.is() )
1877 uno::Reference
<container::XIndexAccess
> xLevels
= new ScNameToIndexAccess( xHierSupp
->getLevels() );
1878 uno::Reference
<uno::XInterface
> xLevel
=
1879 ScUnoHelpFunctions::AnyToInterface( xLevels
->getByIndex( 0 ) );
1880 uno::Reference
<beans::XPropertySet
> xLevProp( xLevel
, uno::UNO_QUERY
);
1881 if ( xLevProp
.is() )
1883 rData
.mbShowAll
= ScUnoHelpFunctions::GetBoolProperty( xLevProp
,
1884 rtl::OUString::createFromAscii(DP_PROP_SHOWEMPTY
) );
1888 xLevProp
->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNO_SORTING
) ) )
1889 >>= rData
.maSortInfo
;
1890 xLevProp
->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNO_LAYOUT
) ) )
1891 >>= rData
.maLayoutInfo
;
1892 xLevProp
->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNO_AUTOSHOW
) ) )
1893 >>= rData
.maShowInfo
;
1895 catch(uno::Exception
&)
1903 BOOL
ScDPObject::FillLabelData(ScPivotParam
& rParam
)
1905 rParam
.maLabelArray
.clear();
1907 ((ScDPObject
*)this)->CreateObjects();
1909 uno::Reference
<container::XNameAccess
> xDimsName
= xSource
->getDimensions();
1910 uno::Reference
<container::XIndexAccess
> xDims
= new ScNameToIndexAccess( xDimsName
);
1911 long nDimCount
= xDims
->getCount();
1912 if ( nDimCount
> MAX_LABELS
)
1913 nDimCount
= MAX_LABELS
;
1917 for (long nDim
=0; nDim
< nDimCount
; nDim
++)
1920 uno::Reference
<uno::XInterface
> xIntDim
=
1921 ScUnoHelpFunctions::AnyToInterface( xDims
->getByIndex(nDim
) );
1922 uno::Reference
<container::XNamed
> xDimName( xIntDim
, uno::UNO_QUERY
);
1923 uno::Reference
<beans::XPropertySet
> xDimProp( xIntDim
, uno::UNO_QUERY
);
1925 if ( xDimName
.is() && xDimProp
.is() )
1927 BOOL bDuplicated
= FALSE
;
1928 BOOL bData
= ScUnoHelpFunctions::GetBoolProperty( xDimProp
,
1929 rtl::OUString::createFromAscii(DP_PROP_ISDATALAYOUT
) );
1930 //! error checking -- is "IsDataLayoutDimension" property required??
1934 aFieldName
= String( xDimName
->getName() );
1936 uno::Any aOrigAny
= xDimProp
->getPropertyValue(
1937 rtl::OUString::createFromAscii(DP_PROP_ORIGINAL
) );
1938 uno::Reference
<uno::XInterface
> xIntOrig
;
1939 if ( (aOrigAny
>>= xIntOrig
) && xIntOrig
.is() )
1942 catch(uno::Exception
&)
1946 OUString aLayoutName
= ScUnoHelpFunctions::GetStringProperty(
1947 xDimProp
, OUString::createFromAscii(SC_UNO_LAYOUTNAME
), OUString());
1949 if ( aFieldName
.Len() && !bData
&& !bDuplicated
)
1951 SCsCOL nCol
= static_cast< SCsCOL
>( nDim
); //! ???
1952 bool bIsValue
= true; //! check
1954 ScDPLabelDataRef
pNewLabel(new ScDPLabelData(aFieldName
, nCol
, bIsValue
));
1955 pNewLabel
->maLayoutName
= aLayoutName
;
1956 GetHierarchies(nDim
, pNewLabel
->maHiers
);
1957 GetMembers(nDim
, GetUsedHierarchy(nDim
), pNewLabel
->maMembers
);
1958 lcl_FillLabelData(*pNewLabel
, xDimProp
);
1959 rParam
.maLabelArray
.push_back(pNewLabel
);
1967 BOOL
ScDPObject::GetHierarchiesNA( sal_Int32 nDim
, uno::Reference
< container::XNameAccess
>& xHiers
)
1970 uno::Reference
<container::XNameAccess
> xDimsName( GetSource()->getDimensions() );
1971 uno::Reference
<container::XIndexAccess
> xIntDims(new ScNameToIndexAccess( xDimsName
));
1974 uno::Reference
<sheet::XHierarchiesSupplier
> xHierSup(xIntDims
->getByIndex( nDim
), uno::UNO_QUERY
);
1977 xHiers
.set( xHierSup
->getHierarchies() );
1984 BOOL
ScDPObject::GetHierarchies( sal_Int32 nDim
, uno::Sequence
< rtl::OUString
>& rHiers
)
1987 uno::Reference
< container::XNameAccess
> xHiersNA
;
1988 if( GetHierarchiesNA( nDim
, xHiersNA
) )
1990 rHiers
= xHiersNA
->getElementNames();
1996 sal_Int32
ScDPObject::GetUsedHierarchy( sal_Int32 nDim
)
1998 sal_Int32 nHier
= 0;
1999 uno::Reference
<container::XNameAccess
> xDimsName( GetSource()->getDimensions() );
2000 uno::Reference
<container::XIndexAccess
> xIntDims(new ScNameToIndexAccess( xDimsName
));
2001 uno::Reference
<beans::XPropertySet
> xDim(xIntDims
->getByIndex( nDim
), uno::UNO_QUERY
);
2003 nHier
= ScUnoHelpFunctions::GetLongProperty( xDim
, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( SC_UNO_USEDHIER
) ) );
2007 BOOL
ScDPObject::GetMembersNA( sal_Int32 nDim
, uno::Reference
< container::XNameAccess
>& xMembers
)
2009 return GetMembersNA( nDim
, GetUsedHierarchy( nDim
), xMembers
);
2012 BOOL
ScDPObject::GetMembersNA( sal_Int32 nDim
, sal_Int32 nHier
, uno::Reference
< container::XNameAccess
>& xMembers
)
2015 uno::Reference
<container::XNameAccess
> xDimsName( GetSource()->getDimensions() );
2016 uno::Reference
<container::XIndexAccess
> xIntDims(new ScNameToIndexAccess( xDimsName
));
2017 uno::Reference
<beans::XPropertySet
> xDim(xIntDims
->getByIndex( nDim
), uno::UNO_QUERY
);
2020 uno::Reference
<sheet::XHierarchiesSupplier
> xHierSup(xDim
, uno::UNO_QUERY
);
2023 uno::Reference
<container::XIndexAccess
> xHiers(new ScNameToIndexAccess(xHierSup
->getHierarchies()));
2024 uno::Reference
<sheet::XLevelsSupplier
> xLevSupp( xHiers
->getByIndex(nHier
), uno::UNO_QUERY
);
2025 if ( xLevSupp
.is() )
2027 uno::Reference
<container::XIndexAccess
> xLevels(new ScNameToIndexAccess( xLevSupp
->getLevels()));
2030 sal_Int32 nLevCount
= xLevels
->getCount();
2033 uno::Reference
<sheet::XMembersSupplier
> xMembSupp( xLevels
->getByIndex(0), uno::UNO_QUERY
);
2034 if ( xMembSupp
.is() )
2036 xMembers
.set(xMembSupp
->getMembers());
2047 //------------------------------------------------------------------------
2048 // convert old pivot tables into new datapilot tables
2050 String
lcl_GetDimName( const uno::Reference
<sheet::XDimensionsSupplier
>& xSource
, long nDim
)
2052 rtl::OUString aName
;
2055 uno::Reference
<container::XNameAccess
> xDimsName
= xSource
->getDimensions();
2056 uno::Reference
<container::XIndexAccess
> xDims
= new ScNameToIndexAccess( xDimsName
);
2057 long nDimCount
= xDims
->getCount();
2058 if ( nDim
< nDimCount
)
2060 uno::Reference
<uno::XInterface
> xIntDim
=
2061 ScUnoHelpFunctions::AnyToInterface( xDims
->getByIndex(nDim
) );
2062 uno::Reference
<container::XNamed
> xDimName( xIntDim
, uno::UNO_QUERY
);
2067 aName
= xDimName
->getName();
2069 catch(uno::Exception
&)
2079 void ScDPObject::ConvertOrientation( ScDPSaveData
& rSaveData
,
2080 PivotField
* pFields
, SCSIZE nCount
, USHORT nOrient
,
2081 ScDocument
* pDoc
, SCROW nRow
, SCTAB nTab
,
2082 const uno::Reference
<sheet::XDimensionsSupplier
>& xSource
,
2084 PivotField
* pRefColFields
, SCSIZE nRefColCount
,
2085 PivotField
* pRefRowFields
, SCSIZE nRefRowCount
,
2086 PivotField
* pRefPageFields
, SCSIZE nRefPageCount
)
2088 // pDoc or xSource must be set
2089 DBG_ASSERT( pDoc
|| xSource
.is(), "missing string source" );
2092 ScDPSaveDimension
* pDim
;
2094 for (SCSIZE i
=0; i
<nCount
; i
++)
2096 SCCOL nCol
= pFields
[i
].nCol
;
2097 USHORT nFuncs
= pFields
[i
].nFuncMask
;
2098 const sheet::DataPilotFieldReference
& rFieldRef
= pFields
[i
].maFieldRef
;
2100 if ( nCol
== PIVOT_DATA_FIELD
)
2101 pDim
= rSaveData
.GetDataLayoutDimension();
2105 pDoc
->GetString( nCol
, nRow
, nTab
, aDocStr
);
2107 aDocStr
= lcl_GetDimName( xSource
, nCol
); // cols must start at 0
2109 if ( aDocStr
.Len() )
2110 pDim
= rSaveData
.GetDimensionByName(aDocStr
);
2117 if ( nOrient
== sheet::DataPilotFieldOrientation_DATA
) // set summary function
2119 // generate an individual entry for each function
2122 // if a dimension is used for column/row/page and data,
2123 // use duplicated dimensions for all data occurrences
2125 for (SCSIZE nRefCol
=0; nRefCol
<nRefColCount
; nRefCol
++)
2126 if (pRefColFields
[nRefCol
].nCol
== nCol
)
2129 for (SCSIZE nRefRow
=0; nRefRow
<nRefRowCount
; nRefRow
++)
2130 if (pRefRowFields
[nRefRow
].nCol
== nCol
)
2133 for (USHORT nRefPage
=0; nRefPage
<nRefPageCount
; ++nRefPage
)
2134 if (pRefPageFields
[nRefPage
].nCol
== nCol
)
2137 // if set via api, a data column may occur several times
2138 // (if the function hasn't been changed yet) -> also look for duplicate data column
2139 for (SCSIZE nPrevData
=0; nPrevData
<i
; nPrevData
++)
2140 if (pFields
[nPrevData
].nCol
== nCol
)
2144 for (USHORT nBit
=0; nBit
<16; nBit
++)
2146 if ( nFuncs
& nMask
)
2148 sheet::GeneralFunction eFunc
= ScDataPilotConversion::FirstFunc( nMask
);
2149 ScDPSaveDimension
* pCurrDim
= bFirst
? pDim
: rSaveData
.DuplicateDimension(pDim
->GetName());
2150 pCurrDim
->SetOrientation( nOrient
);
2151 pCurrDim
->SetFunction( sal::static_int_cast
<USHORT
>(eFunc
) );
2153 if( rFieldRef
.ReferenceType
== sheet::DataPilotFieldReferenceType::NONE
)
2154 pCurrDim
->SetReferenceValue( 0 );
2156 pCurrDim
->SetReferenceValue( &rFieldRef
);
2163 else // set SubTotals
2165 pDim
->SetOrientation( nOrient
);
2167 USHORT nFuncArray
[16];
2168 USHORT nFuncCount
= 0;
2170 for (USHORT nBit
=0; nBit
<16; nBit
++)
2172 if ( nFuncs
& nMask
)
2173 nFuncArray
[nFuncCount
++] = sal::static_int_cast
<USHORT
>(ScDataPilotConversion::FirstFunc( nMask
));
2176 pDim
->SetSubTotals( nFuncCount
, nFuncArray
);
2178 // ShowEmpty was implicit in old tables,
2179 // must be set for data layout dimension (not accessible in dialog)
2180 if ( bOldDefaults
|| nCol
== PIVOT_DATA_FIELD
)
2181 pDim
->SetShowEmpty( TRUE
);
2187 // -----------------------------------------------------------------------
2190 BOOL
ScDPObject::HasRegisteredSources()
2192 BOOL bFound
= FALSE
;
2194 uno::Reference
<lang::XMultiServiceFactory
> xManager
= comphelper::getProcessServiceFactory();
2195 uno::Reference
<container::XContentEnumerationAccess
> xEnAc( xManager
, uno::UNO_QUERY
);
2198 uno::Reference
<container::XEnumeration
> xEnum
= xEnAc
->createContentEnumeration(
2199 rtl::OUString::createFromAscii( SCDPSOURCE_SERVICE
) );
2200 if ( xEnum
.is() && xEnum
->hasMoreElements() )
2208 uno::Sequence
<rtl::OUString
> ScDPObject::GetRegisteredSources()
2211 uno::Sequence
<rtl::OUString
> aSeq(0);
2213 // use implementation names...
2215 uno::Reference
<lang::XMultiServiceFactory
> xManager
= comphelper::getProcessServiceFactory();
2216 uno::Reference
<container::XContentEnumerationAccess
> xEnAc( xManager
, uno::UNO_QUERY
);
2219 uno::Reference
<container::XEnumeration
> xEnum
= xEnAc
->createContentEnumeration(
2220 rtl::OUString::createFromAscii( SCDPSOURCE_SERVICE
) );
2223 while ( xEnum
->hasMoreElements() )
2225 uno::Any aAddInAny
= xEnum
->nextElement();
2226 // if ( aAddInAny.getReflection()->getTypeClass() == TypeClass_INTERFACE )
2228 uno::Reference
<uno::XInterface
> xIntFac
;
2229 aAddInAny
>>= xIntFac
;
2232 uno::Reference
<lang::XServiceInfo
> xInfo( xIntFac
, uno::UNO_QUERY
);
2235 rtl::OUString sName
= xInfo
->getImplementationName();
2237 aSeq
.realloc( nCount
+1 );
2238 aSeq
.getArray()[nCount
] = sName
;
2251 uno::Reference
<sheet::XDimensionsSupplier
> ScDPObject::CreateSource( const ScDPServiceDesc
& rDesc
)
2253 rtl::OUString aImplName
= rDesc
.aServiceName
;
2254 uno::Reference
<sheet::XDimensionsSupplier
> xRet
= NULL
;
2256 uno::Reference
<lang::XMultiServiceFactory
> xManager
= comphelper::getProcessServiceFactory();
2257 uno::Reference
<container::XContentEnumerationAccess
> xEnAc( xManager
, uno::UNO_QUERY
);
2260 uno::Reference
<container::XEnumeration
> xEnum
= xEnAc
->createContentEnumeration(
2261 rtl::OUString::createFromAscii( SCDPSOURCE_SERVICE
) );
2264 while ( xEnum
->hasMoreElements() && !xRet
.is() )
2266 uno::Any aAddInAny
= xEnum
->nextElement();
2267 // if ( aAddInAny.getReflection()->getTypeClass() == TypeClass_INTERFACE )
2269 uno::Reference
<uno::XInterface
> xIntFac
;
2270 aAddInAny
>>= xIntFac
;
2273 uno::Reference
<lang::XServiceInfo
> xInfo( xIntFac
, uno::UNO_QUERY
);
2274 uno::Reference
<lang::XSingleServiceFactory
> xFac( xIntFac
, uno::UNO_QUERY
);
2275 if ( xFac
.is() && xInfo
.is() && xInfo
->getImplementationName() == aImplName
)
2279 uno::Reference
<uno::XInterface
> xInterface
= xFac
->createInstance();
2280 uno::Reference
<lang::XInitialization
> xInit( xInterface
, uno::UNO_QUERY
);
2284 uno::Sequence
<uno::Any
> aSeq(4);
2285 uno::Any
* pArray
= aSeq
.getArray();
2286 pArray
[0] <<= rtl::OUString( rDesc
.aParSource
);
2287 pArray
[1] <<= rtl::OUString( rDesc
.aParName
);
2288 pArray
[2] <<= rtl::OUString( rDesc
.aParUser
);
2289 pArray
[3] <<= rtl::OUString( rDesc
.aParPass
);
2290 xInit
->initialize( aSeq
);
2292 xRet
= uno::Reference
<sheet::XDimensionsSupplier
>( xInterface
, uno::UNO_QUERY
);
2294 catch(uno::Exception
&)
2307 // ============================================================================
2309 ScDPCacheCell::ScDPCacheCell() :
2310 mnStrId(ScSimpleSharedString::EMPTY
),
2311 mnType(SC_VALTYPE_EMPTY
),
2317 ScDPCacheCell::ScDPCacheCell(const ScDPCacheCell
& r
) :
2321 mbNumeric(r
.mbNumeric
)
2325 ScDPCacheCell::~ScDPCacheCell()
2329 // ============================================================================
2331 size_t ScDPCollection::CacheCellHash::operator()(const ScDPCacheCell
* pCell
) const
2333 return pCell
->mnStrId
+ static_cast<size_t>(pCell
->mnType
) +
2334 static_cast<size_t>(pCell
->mfValue
) + static_cast<size_t>(pCell
->mbNumeric
);
2337 bool ScDPCollection::CacheCellEqual::operator()(const ScDPCacheCell
* p1
, const ScDPCacheCell
* p2
) const
2342 if ((!p1
&& p2
) || (p1
&& !p2
))
2345 return p1
->mnStrId
== p2
->mnStrId
&& p1
->mfValue
== p2
->mfValue
&&
2346 p1
->mbNumeric
== p2
->mbNumeric
&& p1
->mnType
== p2
->mnType
;
2349 // ----------------------------------------------------------------------------
2351 ScDPCollection::ScDPCollection(ScDocument
* pDocument
) :
2356 ScDPCollection::ScDPCollection(const ScDPCollection
& r
) :
2359 maSharedString(r
.maSharedString
),
2360 maCacheCellPool() // #i101725# don't copy hash_set with pointers from the other collection
2364 ScDPCollection::~ScDPCollection()
2366 clearCacheCellPool();
2369 ScDataObject
* ScDPCollection::Clone() const
2371 return new ScDPCollection(*this);
2374 void ScDPCollection::DeleteOnTab( SCTAB nTab
)
2377 while ( nPos
< nCount
)
2379 // look for output positions on the deleted sheet
2380 if ( static_cast<const ScDPObject
*>(At(nPos
))->GetOutRange().aStart
.Tab() == nTab
)
2387 void ScDPCollection::UpdateReference( UpdateRefMode eUpdateRefMode
,
2388 const ScRange
& r
, SCsCOL nDx
, SCsROW nDy
, SCsTAB nDz
)
2390 for (USHORT i
=0; i
<nCount
; i
++)
2391 ((ScDPObject
*)At(i
))->UpdateReference( eUpdateRefMode
, r
, nDx
, nDy
, nDz
);
2394 BOOL
ScDPCollection::RefsEqual( const ScDPCollection
& r
) const
2396 if ( nCount
!= r
.nCount
)
2399 for (USHORT i
=0; i
<nCount
; i
++)
2400 if ( ! ((const ScDPObject
*)At(i
))->RefsEqual( *((const ScDPObject
*)r
.At(i
)) ) )
2403 return TRUE
; // all equal
2406 void ScDPCollection::WriteRefsTo( ScDPCollection
& r
) const
2408 if ( nCount
== r
.nCount
)
2410 //! assert equal names?
2411 for (USHORT i
=0; i
<nCount
; i
++)
2412 ((const ScDPObject
*)At(i
))->WriteRefsTo( *((ScDPObject
*)r
.At(i
)) );
2416 // #i8180# If data pilot tables were deleted with their sheet,
2417 // this collection contains extra entries that must be restored.
2418 // Matching objects are found by their names.
2420 DBG_ASSERT( nCount
>= r
.nCount
, "WriteRefsTo: missing entries in document" );
2421 for (USHORT nSourcePos
=0; nSourcePos
<nCount
; nSourcePos
++)
2423 const ScDPObject
* pSourceObj
= static_cast<const ScDPObject
*>(At(nSourcePos
));
2424 String aName
= pSourceObj
->GetName();
2425 bool bFound
= false;
2426 for (USHORT nDestPos
=0; nDestPos
<r
.nCount
&& !bFound
; nDestPos
++)
2428 ScDPObject
* pDestObj
= static_cast<ScDPObject
*>(r
.At(nDestPos
));
2429 if ( pDestObj
->GetName() == aName
)
2431 pSourceObj
->WriteRefsTo( *pDestObj
); // found object, copy refs
2437 // none found, re-insert deleted object (see ScUndoDataPilot::Undo)
2439 ScDPObject
* pDestObj
= new ScDPObject( *pSourceObj
);
2440 pDestObj
->SetAlive(TRUE
);
2441 if ( !r
.InsertNewTable(pDestObj
) )
2443 DBG_ERROR("cannot insert DPObject");
2444 DELETEZ( pDestObj
);
2448 DBG_ASSERT( nCount
== r
.nCount
, "WriteRefsTo: couldn't restore all entries" );
2452 String
ScDPCollection::CreateNewName( USHORT nMin
) const
2454 String aBase
= String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("DataPilot"));
2457 for (USHORT nAdd
=0; nAdd
<=nCount
; nAdd
++) // nCount+1 tries
2459 String aNewName
= aBase
;
2460 aNewName
+= String::CreateFromInt32( nMin
+ nAdd
);
2461 BOOL bFound
= FALSE
;
2462 for (USHORT i
=0; i
<nCount
&& !bFound
; i
++)
2463 if (((const ScDPObject
*)pItems
[i
])->GetName() == aNewName
)
2466 return aNewName
; // found unused Name
2468 return String(); // should not happen
2471 ScSimpleSharedString
& ScDPCollection::GetSharedString()
2473 return maSharedString
;
2476 void ScDPCollection::FreeTable(ScDPObject
* pDPObj
)
2478 const ScRange
& rOutRange
= pDPObj
->GetOutRange();
2479 const ScAddress
& s
= rOutRange
.aStart
;
2480 const ScAddress
& e
= rOutRange
.aEnd
;
2481 pDoc
->RemoveFlagsTab(s
.Col(), s
.Row(), e
.Col(), e
.Row(), s
.Tab(), SC_MF_DP_TABLE
);
2485 bool ScDPCollection::InsertNewTable(ScDPObject
* pDPObj
)
2487 bool bSuccess
= Insert(pDPObj
);
2490 const ScRange
& rOutRange
= pDPObj
->GetOutRange();
2491 const ScAddress
& s
= rOutRange
.aStart
;
2492 const ScAddress
& e
= rOutRange
.aEnd
;
2493 pDoc
->ApplyFlagsTab(s
.Col(), s
.Row(), e
.Col(), e
.Row(), s
.Tab(), SC_MF_DP_TABLE
);
2498 bool ScDPCollection::HasDPTable(SCCOL nCol
, SCROW nRow
, SCTAB nTab
) const
2500 const ScMergeFlagAttr
* pMergeAttr
= static_cast<const ScMergeFlagAttr
*>(
2501 pDoc
->GetAttr(nCol
, nRow
, nTab
, ATTR_MERGE_FLAG
));
2506 return pMergeAttr
->HasDPTable();
2509 ScDPCacheCell
* ScDPCollection::getCacheCellFromPool(const ScDPCacheCell
& rCell
)
2511 ScDPCacheCell
aCell(rCell
);
2512 CacheCellPoolType::iterator itr
= maCacheCellPool
.find(&aCell
);
2513 if (itr
== maCacheCellPool
.end())
2515 // Insert a new instance.
2516 ScDPCacheCell
* p
= new ScDPCacheCell(rCell
);
2517 ::std::pair
<CacheCellPoolType::iterator
, bool> r
=
2518 maCacheCellPool
.insert(p
);
2522 ScDPCacheCell
* p2
= r
.second
? *r
.first
: NULL
;
2523 DBG_ASSERT(p
== p2
, "ScDPCollection::getCacheCellFromPool: pointer addresses differ");
2531 class DeleteCacheCells
: public ::std::unary_function
<ScDPCacheCell
*, void>
2534 void operator()(ScDPCacheCell
* p
) const
2542 void ScDPCollection::clearCacheCellPool()
2544 // Transferring all stored pointers to a vector first. For some unknown
2545 // reason, deleting cell content instances by directly iterating through
2546 // the hash set causes the iteration to return an identical pointer
2547 // value twice, causing a double-delete. I have no idea why this happens.
2550 using ::std::back_inserter
;
2552 vector
<ScDPCacheCell
*> ps
;
2553 ps
.reserve(maCacheCellPool
.size());
2554 copy(maCacheCellPool
.begin(), maCacheCellPool
.end(), back_inserter(ps
));
2555 maCacheCellPool
.clear();
2556 // for correctness' sake, delete the elements after clearing the hash_set
2557 for_each(ps
.begin(), ps
.end(), DeleteCacheCells());