diff options
author | Kohei Yoshida <kohei@openoffice.org> | 2009-06-19 02:29:09 +0000 |
---|---|---|
committer | Kohei Yoshida <kohei@openoffice.org> | 2009-06-19 02:29:09 +0000 |
commit | 621ea5f0e56231a7d5063e6d12cce8aab55af37c (patch) | |
tree | ff8c9a18e1c4d4a9a4d79209f37f01e3e3785c1f /sc | |
parent | acd89bd93d510281d1e46ca1617ff8545d0e981b (diff) |
#i22029# #i81335# applied & adjusted the patch from ooo-build.
This enables changing the names of fields, field members and
grand total names.
Diffstat (limited to 'sc')
27 files changed, 1219 insertions, 321 deletions
diff --git a/sc/inc/dpgroup.hxx b/sc/inc/dpgroup.hxx index 99dac0e517db..cb933f4d2a98 100644 --- a/sc/inc/dpgroup.hxx +++ b/sc/inc/dpgroup.hxx @@ -33,6 +33,7 @@ #include <vector> #include <hash_set> +#include <boost/shared_ptr.hpp> #include "dptabdat.hxx" #include "scdllapi.h" @@ -182,7 +183,7 @@ class ScDPGroupTableData : public ScDPTableData { typedef ::std::hash_set< ::rtl::OUString, ::rtl::OUStringHash, ::std::equal_to< ::rtl::OUString > > StringHashSet; - ScDPTableData* pSourceData; + ::boost::shared_ptr<ScDPTableData> pSourceData; long nSourceCount; ScDPGroupDimensionVec aGroups; ScDPNumGroupDimension* pNumGroups; // array[nSourceCount] @@ -200,7 +201,7 @@ class ScDPGroupTableData : public ScDPTableData public: // takes ownership of pSource - ScDPGroupTableData( ScDPTableData* pSource, ScDocument* pDocument ); + ScDPGroupTableData( const ::boost::shared_ptr<ScDPTableData>& pSource, ScDocument* pDocument ); virtual ~ScDPGroupTableData(); void AddGroupDimension( const ScDPGroupDimension& rGroup ); diff --git a/sc/inc/dpobject.hxx b/sc/inc/dpobject.hxx index 1c50c773b4df..f90277769cba 100644 --- a/sc/inc/dpobject.hxx +++ b/sc/inc/dpobject.hxx @@ -38,6 +38,8 @@ #include "dpoutput.hxx" #include <com/sun/star/sheet/XDimensionsSupplier.hpp> +#include <boost/shared_ptr.hpp> + //------------------------------------------------------------------ namespace com { namespace sun { namespace star { namespace sheet { @@ -66,6 +68,7 @@ class ScStrCollection; class TypedScStrCollection; struct PivotField; class ScDPCacheTable; +class ScDPTableData; struct ScDPServiceDesc { @@ -101,6 +104,7 @@ private: ScSheetSourceDesc* pSheetDesc; // for sheet data ScImportSourceDesc* pImpDesc; // for database data ScDPServiceDesc* pServDesc; // for external service + ::boost::shared_ptr<ScDPTableData> mpTableData; // cached data com::sun::star::uno::Reference<com::sun::star::sheet::XDimensionsSupplier> xSource; ScDPOutput* pOutput; @@ -112,6 +116,7 @@ private: bool mbHeaderLayout; // TRUE : grid, FALSE : standard + SC_DLLPRIVATE ScDPTableData* GetTableData(); SC_DLLPRIVATE void CreateObjects(); SC_DLLPRIVATE void CreateOutput(); @@ -166,7 +171,14 @@ public: void SetTag(const String& rNew); const String& GetTag() const { return aTableTag; } - BOOL IsDimNameInUse( const String& rName ) const; + /** + * Data description cell displays the description of a data dimension if + * and only if there is only one data dimension. It's usually located at + * the upper-left corner of the table output. + */ + bool IsDataDescriptionCell(const ScAddress& rPos); + + bool IsDimNameInUse(const ::rtl::OUString& rName) const; String GetDimName( long nDim, BOOL& rIsDataLayout ); BOOL IsDuplicated( long nDim ); long GetDimCount(); @@ -230,6 +242,8 @@ public: // (button attribute must be present) void RefreshAfterLoad(); + void BuildAllDimensionMembers(); + static BOOL HasRegisteredSources(); static com::sun::star::uno::Sequence<rtl::OUString> GetRegisteredSources(); static com::sun::star::uno::Reference<com::sun::star::sheet::XDimensionsSupplier> diff --git a/sc/inc/dpsave.hxx b/sc/inc/dpsave.hxx index 44689bcf0772..9d680dfa3856 100644 --- a/sc/inc/dpsave.hxx +++ b/sc/inc/dpsave.hxx @@ -34,9 +34,11 @@ #include <tools/string.hxx> #include <tools/list.hxx> #include <com/sun/star/sheet/XDimensionsSupplier.hpp> +#include <com/sun/star/sheet/DataPilotFieldOrientation.hpp> #include "scdllapi.h" #include <hash_map> #include <list> +#include <memory> namespace com { namespace sun { namespace star { namespace sheet { struct DataPilotFieldReference; @@ -46,6 +48,7 @@ namespace com { namespace sun { namespace star { namespace sheet { } } } } class ScDPDimensionSaveData; +class ScDPTableData; // -------------------------------------------------------------------- // @@ -57,6 +60,7 @@ class ScDPSaveMember { private: String aName; + ::std::auto_ptr<rtl::OUString> mpLayoutName; // custom name to be displayed in the table. USHORT nVisibleMode; USHORT nShowDetailsMode; @@ -77,18 +81,23 @@ public: void SetName( const String& rNew ); // used if the source member was renamed (groups) + SC_DLLPUBLIC void SetLayoutName( const ::rtl::OUString& rName ); + SC_DLLPUBLIC const ::rtl::OUString* GetLayoutName() const; + void RemoveLayoutName(); + void WriteToSource( const com::sun::star::uno::Reference< com::sun::star::uno::XInterface>& xMember, sal_Int32 nPosition ); }; -class ScDPSaveDimension +class SC_DLLPUBLIC ScDPSaveDimension { private: String aName; - String* pLayoutName; // alternative name for layout, not used (yet) String* pSelectedPage; + ::std::auto_ptr<rtl::OUString> mpLayoutName; + ::std::auto_ptr<rtl::OUString> mpSubtotalName; BOOL bIsDataLayout; BOOL bDupFlag; USHORT nOrientation; @@ -127,39 +136,44 @@ public: void SetName( const String& rNew ); // used if the source dim was renamed (groups) - SC_DLLPUBLIC void SetOrientation(USHORT nNew); + void SetOrientation(USHORT nNew); void SetSubTotals(BOOL bSet); // to be removed! - SC_DLLPUBLIC void SetSubTotals(long nCount, const USHORT* pFuncs); + void SetSubTotals(long nCount, const USHORT* pFuncs); long GetSubTotalsCount() const { return nSubTotalCount; } USHORT GetSubTotalFunc(long nIndex) const { return pSubTotalFuncs[nIndex]; } - SC_DLLPUBLIC void SetShowEmpty(BOOL bSet); + void SetShowEmpty(BOOL bSet); BOOL GetShowEmpty() const { return BOOL(nShowEmptyMode); } - SC_DLLPUBLIC void SetFunction(USHORT nNew); // enum GeneralFunction + void SetFunction(USHORT nNew); // enum GeneralFunction USHORT GetFunction() const { return nFunction; } void SetUsedHierarchy(long nNew); long GetUsedHierarchy() const { return nUsedHierarchy; } - SC_DLLPUBLIC void SetLayoutName(const String* pName); - SC_DLLPUBLIC const String& GetLayoutName() const; - SC_DLLPUBLIC BOOL HasLayoutName() const; + + void SetLayoutName(const ::rtl::OUString& rName); + const ::rtl::OUString* GetLayoutName() const; + void RemoveLayoutName(); + void SetSubtotalName(const ::rtl::OUString& rName); + const ::rtl::OUString* GetSubtotalName() const; + + bool IsMemberNameInUse(const ::rtl::OUString& rName) const; const ::com::sun::star::sheet::DataPilotFieldReference* GetReferenceValue() const { return pReferenceValue; } - SC_DLLPUBLIC void SetReferenceValue(const ::com::sun::star::sheet::DataPilotFieldReference* pNew); + void SetReferenceValue(const ::com::sun::star::sheet::DataPilotFieldReference* pNew); const ::com::sun::star::sheet::DataPilotFieldSortInfo* GetSortInfo() const { return pSortInfo; } - SC_DLLPUBLIC void SetSortInfo(const ::com::sun::star::sheet::DataPilotFieldSortInfo* pNew); + void SetSortInfo(const ::com::sun::star::sheet::DataPilotFieldSortInfo* pNew); const ::com::sun::star::sheet::DataPilotFieldAutoShowInfo* GetAutoShowInfo() const { return pAutoShowInfo; } - SC_DLLPUBLIC void SetAutoShowInfo(const ::com::sun::star::sheet::DataPilotFieldAutoShowInfo* pNew); + void SetAutoShowInfo(const ::com::sun::star::sheet::DataPilotFieldAutoShowInfo* pNew); const ::com::sun::star::sheet::DataPilotFieldLayoutInfo* GetLayoutInfo() const { return pLayoutInfo; } - SC_DLLPUBLIC void SetLayoutInfo(const ::com::sun::star::sheet::DataPilotFieldLayoutInfo* pNew); + void SetLayoutInfo(const ::com::sun::star::sheet::DataPilotFieldLayoutInfo* pNew); - SC_DLLPUBLIC void SetCurrentPage( const String* pPage ); // NULL = no selection (all) - SC_DLLPUBLIC BOOL HasCurrentPage() const; - SC_DLLPUBLIC const String& GetCurrentPage() const; + void SetCurrentPage( const String* pPage ); // NULL = no selection (all) + BOOL HasCurrentPage() const; + const String& GetCurrentPage() const; USHORT GetOrientation() const { return nOrientation; } ScDPSaveMember* GetExistingMemberByName(const String& rName); - SC_DLLPUBLIC ScDPSaveMember* GetMemberByName(const String& rName); + ScDPSaveMember* GetMemberByName(const String& rName); void SetMemberPosition( const String& rName, sal_Int32 nNewPos ); @@ -180,6 +194,12 @@ private: BOOL bFilterButton; // not passed to DataPilotSource BOOL bDrillDown; // not passed to DataPilotSource + /** if true, all dimensions already have all of their member instances + * created. */ + bool mbDimensionMembersBuilt; + + ::std::auto_ptr<rtl::OUString> mpGrandTotalName; + public: SC_DLLPUBLIC ScDPSaveData(); ScDPSaveData(const ScDPSaveData& r); @@ -189,21 +209,26 @@ public: BOOL operator== ( const ScDPSaveData& r ) const; + SC_DLLPUBLIC void SetGrandTotalName(const ::rtl::OUString& rName); + SC_DLLPUBLIC const ::rtl::OUString* GetGrandTotalName() const; + const List& GetDimensions() const { return aDimList; } void AddDimension(ScDPSaveDimension* pDim) { aDimList.Insert(pDim, LIST_APPEND); } ScDPSaveDimension* GetDimensionByName(const String& rName); SC_DLLPUBLIC ScDPSaveDimension* GetDataLayoutDimension(); + SC_DLLPUBLIC ScDPSaveDimension* GetExistingDataLayoutDimension() const; ScDPSaveDimension* DuplicateDimension(const String& rName); SC_DLLPUBLIC ScDPSaveDimension& DuplicateDimension(const ScDPSaveDimension& rDim); - SC_DLLPUBLIC ScDPSaveDimension* GetExistingDimensionByName(const String& rName); + SC_DLLPUBLIC ScDPSaveDimension* GetExistingDimensionByName(const String& rName) const; SC_DLLPUBLIC ScDPSaveDimension* GetNewDimensionByName(const String& rName); void RemoveDimensionByName(const String& rName); ScDPSaveDimension* GetInnermostDimension(USHORT nOrientation); + ScDPSaveDimension* GetFirstDimension(::com::sun::star::sheet::DataPilotFieldOrientation eOrientation); long GetDataDimensionCount() const; @@ -230,6 +255,7 @@ public: const ScDPDimensionSaveData* GetExistingDimensionData() const { return pDimensionData; } SC_DLLPUBLIC ScDPDimensionSaveData* GetDimensionData(); // create if not there void SetDimensionData( const ScDPDimensionSaveData* pNew ); // copied + void BuildAllDimensionMembers(ScDPTableData* pData); }; diff --git a/sc/inc/dptabres.hxx b/sc/inc/dptabres.hxx index 6dfb782b2313..670c5eb566a4 100644 --- a/sc/inc/dptabres.hxx +++ b/sc/inc/dptabres.hxx @@ -41,6 +41,7 @@ #include <hash_map> #include <hash_set> #include <vector> +#include <memory> namespace com { namespace sun { namespace star { namespace sheet { struct DataPilotFieldReference; @@ -262,7 +263,7 @@ public: long GetMeasureCount() const { return nMeasCount; } ScSubTotalFunc GetMeasureFunction(long nMeasure) const; - String GetMeasureString(long nMeasure, BOOL bForce, ScSubTotalFunc eForceFunc) const; + String GetMeasureString(long nMeasure, BOOL bForce, ScSubTotalFunc eForceFunc, bool& rbTotalResult) const; String GetMeasureDimensionName(long nMeasure) const; const ::com::sun::star::sheet::DataPilotFieldReference& GetMeasureRefVal(long nMeasure) const; USHORT GetMeasureRefOrient(long nMeasure) const; @@ -284,6 +285,8 @@ public: const ScDPItemData& rBaseData, long nBaseIndex ) const; BOOL HasCommonElement( const ScDPItemData& rFirstData, long nFirstIndex, const ScDPItemData& rSecondData, long nSecondIndex ) const; + + const ScDPSource* GetSource() const; }; diff --git a/sc/inc/dptabsrc.hxx b/sc/inc/dptabsrc.hxx index 59996d08b8aa..5538959b2dfc 100644 --- a/sc/inc/dptabsrc.hxx +++ b/sc/inc/dptabsrc.hxx @@ -33,6 +33,7 @@ #include <vector> #include <hash_map> +#include <memory> #include <tools/string.hxx> #include <tools/list.hxx> #include "global.hxx" // enum ScSubTotalFunc @@ -108,7 +109,7 @@ class ScDPSource : public cppu::WeakImplHelper6< com::sun::star::lang::XServiceInfo > { private: - ScDPTableData* pData; // data source + ScDPTableData* pData; // data source (ScDPObject manages its life time) ScDPDimensions* pDimensions; // api objects // settings: long nColDims[SC_DAPI_MAXFIELDS]; @@ -136,6 +137,8 @@ private: List aRowLevelList; BOOL bResultOverflow; + ::std::auto_ptr<rtl::OUString> mpGrandTotalName; + void CreateRes_Impl(); void FillMemberResults(); void FillLevelList( USHORT nOrientation, List& rList ); @@ -162,11 +165,15 @@ public: ScDPTableData* GetData() { return pData; } const ScDPTableData* GetData() const { return pData; } + void SetGrandTotalName(const ::rtl::OUString& rName); + const ::rtl::OUString* GetGrandTotalName() const; + USHORT GetOrientation(long nColumn); void SetOrientation(long nColumn, USHORT nNew); long GetPosition(long nColumn); long GetDataDimensionCount(); + ScDPDimension* GetDataDimension(long nIndex); String GetDataDimName(long nIndex); BOOL IsDataLayoutDimension(long nDim); USHORT GetDataLayoutOrientation(); @@ -333,6 +340,8 @@ private: long nUsedHier; USHORT nFunction; // enum GeneralFunction String aName; // if empty, take from source + ::std::auto_ptr<rtl::OUString> mpLayoutName; + ::std::auto_ptr<rtl::OUString> mpSubtotalName; long nSourceDim; // >=0 if dup'ed ::com::sun::star::sheet::DataPilotFieldReference aReferenceValue; // settings for "show data as" / "displayed value" @@ -350,6 +359,9 @@ public: ScDPDimension* CreateCloneObject(); ScDPHierarchies* GetHierarchiesObject(); + SC_DLLPUBLIC const ::rtl::OUString* GetLayoutName() const; + const ::rtl::OUString* GetSubtotalName() const; + // XNamed virtual ::rtl::OUString SAL_CALL getName() throw(::com::sun::star::uno::RuntimeException); virtual void SAL_CALL setName( const ::rtl::OUString& aName ) @@ -736,7 +748,7 @@ private: long nLev; ScDPItemData maData; -// String aCaption; // visible name (changeable by user) + ::std::auto_ptr<rtl::OUString> mpLayoutName; sal_Int32 nPosition; // manual sorting BOOL bVisible; @@ -750,6 +762,7 @@ public: BOOL IsNamedItem( const ScDPItemData& r ) const; String GetNameStr() const; void FillItemData( ScDPItemData& rData ) const; + SC_DLLPUBLIC const ::rtl::OUString* GetLayoutName() const; sal_Int32 Compare( const ScDPMember& rOther ) const; // visible order diff --git a/sc/inc/unonames.hxx b/sc/inc/unonames.hxx index 367e7d7cfe35..bfc5aa9de831 100644 --- a/sc/inc/unonames.hxx +++ b/sc/inc/unonames.hxx @@ -558,6 +558,9 @@ #define SC_UNO_ROWFIELDCOUNT "RowFieldCount" #define SC_UNO_COLUMNFIELDCOUNT "ColumnFieldCount" #define SC_UNO_DATAFIELDCOUNT "DataFieldCount" +#define SC_UNO_LAYOUTNAME "LayoutName" +#define SC_UNO_FIELD_SUBTOTALNAME "FieldSubtotalName" +#define SC_UNO_GRANDTOTAL_NAME "GrandTotalName" // (preliminary:) #define SC_UNO_REFVALUE "ReferenceValue" diff --git a/sc/source/core/data/dpgroup.cxx b/sc/source/core/data/dpgroup.cxx index a92d1681ec0e..037a232bbd2a 100644 --- a/sc/source/core/data/dpgroup.cxx +++ b/sc/source/core/data/dpgroup.cxx @@ -70,6 +70,7 @@ using ::rtl::OUStringHash; using ::std::vector; using ::std::hash_set; using ::std::hash_map; +using ::boost::shared_ptr; #define D_TIMEFACTOR 86400.0 @@ -977,7 +978,7 @@ String lcl_GetNumGroupForValue( double fValue, const ScDPNumGroupInfo& rInfo, bo return lcl_GetNumGroupName( fGroupStart, rInfo, bHasNonInteger, cDecSeparator, pFormatter ); } -ScDPGroupTableData::ScDPGroupTableData( ScDPTableData* pSource, ScDocument* pDocument ) : +ScDPGroupTableData::ScDPGroupTableData( const shared_ptr<ScDPTableData>& pSource, ScDocument* pDocument ) : ScDPTableData(pDocument), pSourceData( pSource ), pDoc( pDocument ) @@ -992,7 +993,6 @@ ScDPGroupTableData::ScDPGroupTableData( ScDPTableData* pSource, ScDocument* pDoc ScDPGroupTableData::~ScDPGroupTableData() { delete[] pNumGroups; - delete pSourceData; } void ScDPGroupTableData::AddGroupDimension( const ScDPGroupDimension& rGroup ) diff --git a/sc/source/core/data/dpobject.cxx b/sc/source/core/data/dpobject.cxx index fa58a8b3c277..cd7d58964a96 100644 --- a/sc/source/core/data/dpobject.cxx +++ b/sc/source/core/data/dpobject.cxx @@ -78,6 +78,7 @@ using namespace com::sun::star; using ::std::vector; +using ::boost::shared_ptr; using ::com::sun::star::uno::Sequence; using ::com::sun::star::uno::Reference; using ::com::sun::star::uno::UNO_QUERY; @@ -162,6 +163,7 @@ ScDPObject::ScDPObject( ScDocument* pD ) : pSheetDesc( NULL ), pImpDesc( NULL ), pServDesc( NULL ), + mpTableData(static_cast<ScDPTableData*>(NULL)), pOutput( NULL ), bSettingsChanged( FALSE ), bAlive( FALSE ), @@ -182,6 +184,7 @@ ScDPObject::ScDPObject(const ScDPObject& r) : pSheetDesc( NULL ), pImpDesc( NULL ), pServDesc( NULL ), + mpTableData(static_cast<ScDPTableData*>(NULL)), pOutput( NULL ), bSettingsChanged( FALSE ), bAlive( FALSE ), @@ -349,6 +352,22 @@ void ScDPObject::SetTag(const String& rNew) aTableTag = rNew; } +bool ScDPObject::IsDataDescriptionCell(const ScAddress& rPos) +{ + if (!pSaveData) + return false; + + long nDataDimCount = pSaveData->GetDataDimensionCount(); + if (nDataDimCount != 1) + // There has to be exactly one data dimension for the description to + // appear at top-left corner. + return false; + + CreateOutput(); + ScRange aTabRange = pOutput->GetOutputRange(sheet::DataPilotOutputRangeType::TABLE); + return (rPos == aTabRange.aStart); +} + uno::Reference<sheet::XDimensionsSupplier> ScDPObject::GetSource() { CreateObjects(); @@ -390,11 +409,43 @@ void ScDPObject::CreateOutput() } } +ScDPTableData* ScDPObject::GetTableData() +{ + if (!mpTableData) + { + if ( pImpDesc ) + { + // database data + mpTableData.reset(new ScDatabaseDPData(pDoc, *pImpDesc)); + } + else + { + // cell data + if (!pSheetDesc) + { + DBG_ERROR("no source descriptor"); + pSheetDesc = new ScSheetSourceDesc; // dummy defaults + } + mpTableData.reset(new ScSheetDPData(pDoc, *pSheetDesc)); + } + + // grouping (for cell or database data) + if ( pSaveData && pSaveData->GetExistingDimensionData() ) + { + shared_ptr<ScDPGroupTableData> pGroupData(new ScDPGroupTableData(mpTableData, pDoc)); + pSaveData->GetExistingDimensionData()->WriteToData(*pGroupData); + mpTableData = pGroupData; + } + } + + return mpTableData.get(); +} + void ScDPObject::CreateObjects() { // if groups are involved, create a new source with the ScDPGroupTableData if ( bSettingsChanged && pSaveData && pSaveData->GetExistingDimensionData() ) - xSource = NULL; + InvalidateSource(); if (!xSource.is()) { @@ -412,33 +463,9 @@ void ScDPObject::CreateObjects() if ( !xSource.is() ) // database or sheet data, or error in CreateSource { DBG_ASSERT( !pServDesc, "DPSource could not be created" ); - - ScDPTableData* pData = NULL; - if ( pImpDesc ) - { - // database data - pData = new ScDatabaseDPData( pDoc, *pImpDesc ); - } - else - { - // cell data - if (!pSheetDesc) - { - DBG_ERROR("no source descriptor"); - pSheetDesc = new ScSheetSourceDesc; // dummy defaults - } - pData = new ScSheetDPData( pDoc, *pSheetDesc ); - } - - // grouping (for cell or database data) - if ( pSaveData && pSaveData->GetExistingDimensionData() ) - { - ScDPGroupTableData* pGroupData = new ScDPGroupTableData( pData, pDoc ); - pSaveData->GetExistingDimensionData()->WriteToData( *pGroupData ); - pData = pGroupData; - } - - xSource = new ScDPSource( pData ); + ScDPTableData* pData = GetTableData(); + ScDPSource* pSource = new ScDPSource( pData ); + xSource = pSource; } if (pSaveData) @@ -475,6 +502,7 @@ void ScDPObject::InvalidateData() void ScDPObject::InvalidateSource() { xSource = NULL; + mpTableData.reset(); } ScRange ScDPObject::GetNewOutputRange( BOOL& rOverflow ) @@ -556,6 +584,14 @@ void ScDPObject::RefreshAfterLoad() nHeaderRows = 0; // nothing found, no drop-down lists } +void ScDPObject::BuildAllDimensionMembers() +{ + if (!pSaveData) + return; + + pSaveData->BuildAllDimensionMembers(GetTableData()); +} + void ScDPObject::UpdateReference( UpdateRefMode eUpdateRefMode, const ScRange& rRange, SCsCOL nDx, SCsROW nDy, SCsTAB nDz ) { @@ -678,23 +714,33 @@ void ScDPObject::GetDrillDownData(const ScAddress& rPos, Sequence< Sequence<Any> rTableData = xDrillDownData->getDrillDownData(filters); } -BOOL ScDPObject::IsDimNameInUse( const String& rName ) const +bool ScDPObject::IsDimNameInUse(const OUString& rName) const { - if ( xSource.is() ) + if (!xSource.is()) + return false; + + Reference<container::XNameAccess> xDims = xSource->getDimensions(); + Sequence<OUString> aDimNames = xDims->getElementNames(); + sal_Int32 n = aDimNames.getLength(); + for (sal_Int32 i = 0; i < n; ++i) { - uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions(); - if ( xDimsName.is() ) + const OUString& rDimName = aDimNames[i]; + if (rDimName.equalsIgnoreAsciiCase(rName)) + return true; + + Reference<beans::XPropertySet> xPropSet(xDims->getByName(rDimName), UNO_QUERY); + if (!xPropSet.is()) + continue; + + Any any = xPropSet->getPropertyValue(OUString::createFromAscii(SC_UNO_LAYOUTNAME)); + OUString aLayoutName; + if (any >>= aLayoutName) { - rtl::OUString aCompare( rName ); - uno::Sequence<rtl::OUString> aNames = xDimsName->getElementNames(); - long nCount = aNames.getLength(); - const rtl::OUString* pArr = aNames.getConstArray(); - for (long nPos=0; nPos<nCount; nPos++) - if ( pArr[nPos] == aCompare ) //! ignore case - return TRUE; + if (aLayoutName.equalsIgnoreAsciiCase(rName)) + return true; } } - return FALSE; // not found + return false; } String ScDPObject::GetDimName( long nDim, BOOL& rIsDataLayout ) diff --git a/sc/source/core/data/dpoutput.cxx b/sc/source/core/data/dpoutput.cxx index 567dcc7991f3..d376ed3cd396 100644 --- a/sc/source/core/data/dpoutput.cxx +++ b/sc/source/core/data/dpoutput.cxx @@ -81,6 +81,7 @@ using namespace com::sun::star; using ::std::vector; +using ::com::sun::star::beans::XPropertySet; using ::com::sun::star::uno::Sequence; using ::com::sun::star::uno::UNO_QUERY; using ::com::sun::star::uno::Reference; @@ -98,7 +99,6 @@ using ::rtl::OUString; #define DP_PROP_ORIENTATION "Orientation" #define DP_PROP_POSITION "Position" #define DP_PROP_USEDHIERARCHY "UsedHierarchy" -#define DP_PROP_DATADESCR "DataDescription" #define DP_PROP_ISDATALAYOUT "IsDataLayoutDimension" #define DP_PROP_NUMBERFORMAT "NumberFormat" #define DP_PROP_FILTER "Filter" @@ -119,7 +119,8 @@ struct ScDPOutLevelData long nLevel; long nDimPos; uno::Sequence<sheet::MemberResult> aResult; - String aCaption; + String maName; /// Name is the internal field name. + String aCaption; /// Caption is the name visible in the output table. ScDPOutLevelData() { nDim = nHier = nLevel = nDimPos = -1; } @@ -444,7 +445,15 @@ ScDPOutput::ScDPOutput( ScDocument* pD, const uno::Reference<sheet::XDimensionsS xLevel, uno::UNO_QUERY ); if ( xLevNam.is() && xLevRes.is() ) { - String aCaption = String(xLevNam->getName()); //! Caption... + String aName = xLevNam->getName(); + OUString aCaption = aName; // Caption equals the field name by default. + Reference<XPropertySet> xPropSet(xLevel, UNO_QUERY); + if (xPropSet.is()) + { + Any any = xPropSet->getPropertyValue( + OUString::createFromAscii(SC_UNO_LAYOUTNAME)); + any >>= aCaption; + } switch ( eDimOrient ) { case sheet::DataPilotFieldOrientation_COLUMN: @@ -453,6 +462,7 @@ ScDPOutput::ScDPOutput( ScDocument* pD, const uno::Reference<sheet::XDimensionsS pColFields[nColFieldCount].nLevel = nLev; pColFields[nColFieldCount].nDimPos = nDimPos; pColFields[nColFieldCount].aResult = xLevRes->getResults(); + pColFields[nColFieldCount].maName = aName; pColFields[nColFieldCount].aCaption= aCaption; if (!lcl_MemberEmpty(pColFields[nColFieldCount].aResult)) ++nColFieldCount; @@ -463,6 +473,7 @@ ScDPOutput::ScDPOutput( ScDocument* pD, const uno::Reference<sheet::XDimensionsS pRowFields[nRowFieldCount].nLevel = nLev; pRowFields[nRowFieldCount].nDimPos = nDimPos; pRowFields[nRowFieldCount].aResult = xLevRes->getResults(); + pRowFields[nRowFieldCount].maName = aName; pRowFields[nRowFieldCount].aCaption= aCaption; if (!lcl_MemberEmpty(pRowFields[nRowFieldCount].aResult)) ++nRowFieldCount; @@ -473,6 +484,7 @@ ScDPOutput::ScDPOutput( ScDocument* pD, const uno::Reference<sheet::XDimensionsS pPageFields[nPageFieldCount].nLevel = nLev; pPageFields[nPageFieldCount].nDimPos = nDimPos; pPageFields[nPageFieldCount].aResult = lcl_GetSelectedPageAsResult(xDimProp); + pPageFields[nPageFieldCount].maName = aName; pPageFields[nPageFieldCount].aCaption= aCaption; // no check on results for page fields ++nPageFieldCount; @@ -529,7 +541,7 @@ ScDPOutput::ScDPOutput( ScDocument* pD, const uno::Reference<sheet::XDimensionsS try { uno::Any aAny = xSrcProp->getPropertyValue( - rtl::OUString::createFromAscii(DP_PROP_DATADESCR) ); + rtl::OUString::createFromAscii(SC_UNO_DATADESC) ); rtl::OUString aUStr; aAny >>= aUStr; aDataDescription = String( aUStr ); @@ -606,9 +618,16 @@ void ScDPOutput::HeaderCell( SCCOL nCol, SCROW nRow, SCTAB nTab, const sheet::MemberResult& rData, BOOL bColHeader, long nLevel ) { long nFlags = rData.Flags; + + rtl::OUStringBuffer aCaptionBuf; + if (!(nFlags & sheet::MemberResultFlags::NUMERIC)) + // This caption is not a number. Make sure it won't get parsed as one. + aCaptionBuf.append(sal_Unicode('\'')); + aCaptionBuf.append(rData.Caption); + if ( nFlags & sheet::MemberResultFlags::HASMEMBER ) { - pDoc->SetString( nCol, nRow, nTab, rData.Caption ); + pDoc->SetString( nCol, nRow, nTab, aCaptionBuf.makeStringAndClear() ); } else { @@ -1161,7 +1180,7 @@ bool ScDPOutput::GetDataResultPositionData(vector<sheet::DataPilotFieldFilter>& for (SCCOL nColField = 0; nColField < nColFieldCount && bFilterByCol; ++nColField) { sheet::DataPilotFieldFilter filter; - filter.FieldName = pColFields[nColField].aCaption; + filter.FieldName = pColFields[nColField].maName; const uno::Sequence<sheet::MemberResult> rSequence = pColFields[nColField].aResult; const sheet::MemberResult* pArray = rSequence.getConstArray(); @@ -1178,10 +1197,15 @@ bool ScDPOutput::GetDataResultPositionData(vector<sheet::DataPilotFieldFilter>& } // row fields + bool bDataLayoutExists = (nDataFieldCount > 1); for (SCROW nRowField = 0; nRowField < nRowFieldCount && bFilterByRow; ++nRowField) { + if (bDataLayoutExists && nRowField == nRowFieldCount - 1) + // There is no sense including the data layout field for filtering. + continue; + sheet::DataPilotFieldFilter filter; - filter.FieldName = pRowFields[nRowField].aCaption; + filter.FieldName = pRowFields[nRowField].maName; const uno::Sequence<sheet::MemberResult> rSequence = pRowFields[nRowField].aResult; const sheet::MemberResult* pArray = rSequence.getConstArray(); @@ -1213,8 +1237,7 @@ bool lcl_IsNamedDataField( const ScDPGetPivotDataField& rTarget, const String& r bool lcl_IsNamedCategoryField( const ScDPGetPivotDataField& rFilter, const ScDPOutLevelData& rField ) { - //! name from source instead of caption? - return ScGlobal::pTransliteration->isEqual( rFilter.maFieldName, rField.aCaption ); + return ScGlobal::pTransliteration->isEqual( rFilter.maFieldName, rField.maName ); } bool lcl_IsCondition( const sheet::MemberResult& rResultEntry, const ScDPGetPivotDataField& rFilter ) diff --git a/sc/source/core/data/dpsave.cxx b/sc/source/core/data/dpsave.cxx index f4180312ce0d..ba1acc97a83a 100644 --- a/sc/source/core/data/dpsave.cxx +++ b/sc/source/core/data/dpsave.cxx @@ -58,7 +58,12 @@ #include <com/sun/star/container/XNamed.hpp> #include <com/sun/star/util/XCloneable.hpp> +#include <hash_map> + using namespace com::sun::star; +using ::rtl::OUString; +using ::std::hash_map; +using ::std::auto_ptr; // ----------------------------------------------------------------------- @@ -113,6 +118,7 @@ void lcl_SkipExtra( SvStream& rStream ) ScDPSaveMember::ScDPSaveMember(const String& rName) : aName( rName ), + mpLayoutName(NULL), nVisibleMode( SC_DPSAVEMODE_DONTKNOW ), nShowDetailsMode( SC_DPSAVEMODE_DONTKNOW ) { @@ -120,9 +126,12 @@ ScDPSaveMember::ScDPSaveMember(const String& rName) : ScDPSaveMember::ScDPSaveMember(const ScDPSaveMember& r) : aName( r.aName ), + mpLayoutName(NULL), nVisibleMode( r.nVisibleMode ), nShowDetailsMode( r.nShowDetailsMode ) { + if (r.mpLayoutName.get()) + mpLayoutName.reset(new OUString(*r.mpLayoutName)); } ScDPSaveMember::~ScDPSaveMember() @@ -167,6 +176,21 @@ void ScDPSaveMember::SetName( const String& rNew ) aName = rNew; } +void ScDPSaveMember::SetLayoutName( const OUString& rName ) +{ + mpLayoutName.reset(new OUString(rName)); +} + +const OUString* ScDPSaveMember::GetLayoutName() const +{ + return mpLayoutName.get(); +} + +void ScDPSaveMember::RemoveLayoutName() +{ + mpLayoutName.reset(NULL); +} + void ScDPSaveMember::WriteToSource( const uno::Reference<uno::XInterface>& xMember, sal_Int32 nPosition ) { // nothing to do? @@ -187,6 +211,18 @@ void ScDPSaveMember::WriteToSource( const uno::Reference<uno::XInterface>& xMemb lcl_SetBoolProperty( xMembProp, rtl::OUString::createFromAscii(DP_PROP_SHOWDETAILS), (BOOL)nShowDetailsMode ); + if (mpLayoutName.get()) + { + try + { + uno::Any any; + any <<= rtl::OUString(*mpLayoutName); + xMembProp->setPropertyValue(rtl::OUString::createFromAscii(SC_UNO_LAYOUTNAME), any); + } + catch (uno::Exception&) + { + } + } if ( nPosition >= 0 ) { try @@ -205,8 +241,9 @@ void ScDPSaveMember::WriteToSource( const uno::Reference<uno::XInterface>& xMemb ScDPSaveDimension::ScDPSaveDimension(const String& rName, BOOL bDataLayout) : aName( rName ), - pLayoutName( NULL ), pSelectedPage( NULL ), + mpLayoutName(NULL), + mpSubtotalName(NULL), bIsDataLayout( bDataLayout ), bDupFlag( FALSE ), nOrientation( sheet::DataPilotFieldOrientation_HIDDEN ), @@ -225,6 +262,8 @@ ScDPSaveDimension::ScDPSaveDimension(const String& rName, BOOL bDataLayout) : ScDPSaveDimension::ScDPSaveDimension(const ScDPSaveDimension& r) : aName( r.aName ), + mpLayoutName(NULL), + mpSubtotalName(NULL), bIsDataLayout( r.bIsDataLayout ), bDupFlag( r.bDupFlag ), nOrientation( r.nOrientation ), @@ -265,14 +304,14 @@ ScDPSaveDimension::ScDPSaveDimension(const ScDPSaveDimension& r) : pLayoutInfo = new sheet::DataPilotFieldLayoutInfo( *(r.pLayoutInfo) ); else pLayoutInfo = NULL; - if (r.pLayoutName) - pLayoutName = new String( *(r.pLayoutName) ); - else - pLayoutName = NULL; if (r.pSelectedPage) pSelectedPage = new String( *(r.pSelectedPage) ); else pSelectedPage = NULL; + if (r.mpLayoutName.get()) + mpLayoutName.reset(new OUString(*r.mpLayoutName)); + if (r.mpSubtotalName.get()) + mpSubtotalName.reset(new OUString(*r.mpSubtotalName)); } ScDPSaveDimension::~ScDPSaveDimension() @@ -283,7 +322,6 @@ ScDPSaveDimension::~ScDPSaveDimension() delete pSortInfo; delete pAutoShowInfo; delete pLayoutInfo; - delete pLayoutName; delete pSelectedPage; delete [] pSubTotalFuncs; } @@ -395,25 +433,45 @@ void ScDPSaveDimension::SetUsedHierarchy(long nNew) nUsedHierarchy = nNew; } -BOOL ScDPSaveDimension::HasLayoutName() const +void ScDPSaveDimension::SetSubtotalName(const OUString& rName) { - return ( pLayoutName != NULL ); + mpSubtotalName.reset(new OUString(rName)); } -void ScDPSaveDimension::SetLayoutName(const String* pName) +const OUString* ScDPSaveDimension::GetSubtotalName() const { - delete pLayoutName; - if (pName) - pLayoutName = new String( *pName ); - else - pLayoutName = NULL; + return mpSubtotalName.get(); +} + +bool ScDPSaveDimension::IsMemberNameInUse(const OUString& rName) const +{ + MemberList::const_iterator itr = maMemberList.begin(), itrEnd = maMemberList.end(); + for (; itr != itrEnd; ++itr) + { + const ScDPSaveMember* pMem = *itr; + if (rName.equalsIgnoreAsciiCase(pMem->GetName())) + return true; + + const OUString* pLayoutName = pMem->GetLayoutName(); + if (pLayoutName && rName.equalsIgnoreAsciiCase(*pLayoutName)) + return true; + } + return false; +} + +void ScDPSaveDimension::SetLayoutName(const OUString& rName) +{ + mpLayoutName.reset(new OUString(rName)); } -const String& ScDPSaveDimension::GetLayoutName() const +const OUString* ScDPSaveDimension::GetLayoutName() const { - if (pLayoutName) - return *pLayoutName; - return aName; + return mpLayoutName.get(); +} + +void ScDPSaveDimension::RemoveLayoutName() +{ + mpLayoutName.reset(NULL); } void ScDPSaveDimension::SetReferenceValue(const sheet::DataPilotFieldReference* pNew) @@ -549,6 +607,19 @@ void ScDPSaveDimension::WriteToSource( const uno::Reference<uno::XInterface>& xD { aAny <<= aFilter; xDimProp->setPropertyValue( rtl::OUString::createFromAscii(DP_PROP_FILTER), aAny ); + if (mpLayoutName.get()) + { + aAny <<= *mpLayoutName; + xDimProp->setPropertyValue(rtl::OUString::createFromAscii(SC_UNO_LAYOUTNAME), aAny); + } + + const OUString* pSubTotalName = GetSubtotalName(); + if (pSubTotalName) + { + // Custom subtotal name, with '?' being replaced by the visible field name later. + aAny <<= *pSubTotalName; + xDimProp->setPropertyValue(OUString::createFromAscii(SC_UNO_FIELD_SUBTOTALNAME), aAny); + } } catch ( beans::UnknownPropertyException& ) { @@ -691,7 +762,9 @@ ScDPSaveData::ScDPSaveData() : nIgnoreEmptyMode( SC_DPSAVEMODE_DONTKNOW ), nRepeatEmptyMode( SC_DPSAVEMODE_DONTKNOW ), bFilterButton( TRUE ), - bDrillDown( TRUE ) + bDrillDown( TRUE ), + mbDimensionMembersBuilt(false), + mpGrandTotalName(NULL) { } @@ -701,7 +774,9 @@ ScDPSaveData::ScDPSaveData(const ScDPSaveData& r) : nIgnoreEmptyMode( r.nIgnoreEmptyMode ), nRepeatEmptyMode( r.nRepeatEmptyMode ), bFilterButton( r.bFilterButton ), - bDrillDown( r.bDrillDown ) + bDrillDown( r.bDrillDown ), + mbDimensionMembersBuilt(r.mbDimensionMembersBuilt), + mpGrandTotalName(NULL) { if ( r.pDimensionData ) pDimensionData = new ScDPDimensionSaveData( *r.pDimensionData ); @@ -714,6 +789,9 @@ ScDPSaveData::ScDPSaveData(const ScDPSaveData& r) : ScDPSaveDimension* pNew = new ScDPSaveDimension( *(ScDPSaveDimension*)r.aDimList.GetObject(i) ); aDimList.Insert( pNew, LIST_APPEND ); } + + if (r.mpGrandTotalName.get()) + mpGrandTotalName.reset(new OUString(*r.mpGrandTotalName)); } ScDPSaveData& ScDPSaveData::operator= ( const ScDPSaveData& r ) @@ -732,6 +810,7 @@ ScDPSaveData& ScDPSaveData::operator= ( const ScDPSaveData& r ) nRepeatEmptyMode = r.nRepeatEmptyMode; bFilterButton = r.bFilterButton; bDrillDown = r.bDrillDown; + mbDimensionMembersBuilt = r.mbDimensionMembersBuilt; // remove old dimensions @@ -750,6 +829,9 @@ ScDPSaveData& ScDPSaveData::operator= ( const ScDPSaveData& r ) new ScDPSaveDimension( *(ScDPSaveDimension*)r.aDimList.GetObject(i) ); aDimList.Insert( pNew, LIST_APPEND ); } + + if (r.mpGrandTotalName.get()) + mpGrandTotalName.reset(new OUString(*r.mpGrandTotalName)); } return *this; } @@ -761,7 +843,8 @@ BOOL ScDPSaveData::operator== ( const ScDPSaveData& r ) const nIgnoreEmptyMode != r.nIgnoreEmptyMode || nRepeatEmptyMode != r.nRepeatEmptyMode || bFilterButton != r.bFilterButton || - bDrillDown != r.bDrillDown ) + bDrillDown != r.bDrillDown || + mbDimensionMembersBuilt != r.mbDimensionMembersBuilt) return FALSE; if ( pDimensionData || r.pDimensionData ) @@ -777,6 +860,16 @@ BOOL ScDPSaveData::operator== ( const ScDPSaveData& r ) const *(ScDPSaveDimension*)r.aDimList.GetObject(i) ) ) return FALSE; + if (mpGrandTotalName.get()) + { + if (!r.mpGrandTotalName.get()) + return false; + if (!mpGrandTotalName->equals(*r.mpGrandTotalName)) + return false; + } + else if (r.mpGrandTotalName.get()) + return false; + return TRUE; } @@ -790,6 +883,16 @@ ScDPSaveData::~ScDPSaveData() delete pDimensionData; } +void ScDPSaveData::SetGrandTotalName(const OUString& rName) +{ + mpGrandTotalName.reset(new OUString(rName)); +} + +const OUString* ScDPSaveData::GetGrandTotalName() const +{ + return mpGrandTotalName.get(); +} + ScDPSaveDimension* ScDPSaveData::GetDimensionByName(const String& rName) { long nCount = aDimList.Count(); @@ -804,7 +907,7 @@ ScDPSaveDimension* ScDPSaveData::GetDimensionByName(const String& rName) return pNew; } -ScDPSaveDimension* ScDPSaveData::GetExistingDimensionByName(const String& rName) +ScDPSaveDimension* ScDPSaveData::GetExistingDimensionByName(const String& rName) const { long nCount = aDimList.Count(); for (long i=0; i<nCount; i++) @@ -832,16 +935,25 @@ ScDPSaveDimension* ScDPSaveData::GetNewDimensionByName(const String& rName) ScDPSaveDimension* ScDPSaveData::GetDataLayoutDimension() { - ULONG nCount = aDimList.Count(); - for (ULONG i=0; i<nCount; i++) + ScDPSaveDimension* pDim = GetExistingDataLayoutDimension(); + if (pDim) + return pDim; + + ScDPSaveDimension* pNew = new ScDPSaveDimension( String(), TRUE ); + aDimList.Insert( pNew, LIST_APPEND ); + return pNew; +} + +ScDPSaveDimension* ScDPSaveData::GetExistingDataLayoutDimension() const +{ + long nCount = aDimList.Count(); + for (long i=0; i<nCount; i++) { ScDPSaveDimension* pDim = (ScDPSaveDimension*)aDimList.GetObject(i); if ( pDim->IsDataLayout() ) return pDim; } - ScDPSaveDimension* pNew = new ScDPSaveDimension( String(), TRUE ); - aDimList.Insert( pNew, LIST_APPEND ); - return pNew; + return NULL; } ScDPSaveDimension* ScDPSaveData::DuplicateDimension(const String& rName) @@ -895,6 +1007,18 @@ ScDPSaveDimension* ScDPSaveData::GetInnermostDimension(USHORT nOrientation) return pInner; // the last matching one } +ScDPSaveDimension* ScDPSaveData::GetFirstDimension(sheet::DataPilotFieldOrientation eOrientation) +{ + long nCount = aDimList.Count(); + for (long i = 0; i < nCount; ++i) + { + ScDPSaveDimension* pDim = static_cast<ScDPSaveDimension*>(aDimList.GetObject(i)); + if (pDim->GetOrientation() == eOrientation && !pDim->IsDataLayout()) + return pDim; + } + return NULL; +} + long ScDPSaveData::GetDataDimensionCount() const { long nDataCount = 0; @@ -1002,6 +1126,14 @@ void ScDPSaveData::WriteToSource( const uno::Reference<sheet::XDimensionsSupplie if ( nRepeatEmptyMode != SC_DPSAVEMODE_DONTKNOW ) lcl_SetBoolProperty( xSourceProp, rtl::OUString::createFromAscii(DP_PROP_REPEATIFEMPTY), (BOOL)nRepeatEmptyMode ); + + const OUString* pGrandTotalName = GetGrandTotalName(); + if (pGrandTotalName) + { + uno::Any any; + any <<= *pGrandTotalName; + xSourceProp->setPropertyValue(OUString::createFromAscii(SC_UNO_GRANDTOTAL_NAME), any); + } } catch(uno::Exception&) { @@ -1125,3 +1257,50 @@ void ScDPSaveData::SetDimensionData( const ScDPDimensionSaveData* pNew ) pDimensionData = NULL; } +void ScDPSaveData::BuildAllDimensionMembers(ScDPTableData* pData) +{ + if (mbDimensionMembersBuilt) + return; + + // First, build a dimension name-to-index map. + typedef hash_map<OUString, long, ::rtl::OUStringHash> NameIndexMap; + NameIndexMap aMap; + long nColCount = pData->GetColumnCount(); + for (long i = 0; i < nColCount; ++i) + aMap.insert( NameIndexMap::value_type(pData->getDimensionName(i), i)); + + NameIndexMap::const_iterator itrEnd = aMap.end(); + + sal_uInt32 n = aDimList.Count(); + for (sal_uInt32 i = 0; i < n; ++i) + { + ScDPSaveDimension* pDim = static_cast<ScDPSaveDimension*>(aDimList.GetObject(i)); + const String& rDimName = pDim->GetName(); + if (!rDimName.Len()) + // empty dimension name. It must be data layout. + continue; + + NameIndexMap::const_iterator itr = aMap.find(rDimName); + if (itr == itrEnd) + // dimension name not in the data. This should never happen! + continue; + + long nDimIndex = itr->second; + const TypedScStrCollection& rMembers = pData->GetColumnEntries(nDimIndex); + sal_uInt16 nMemberCount = rMembers.GetCount(); + for (sal_uInt16 j = 0; j < nMemberCount; ++j) + { + const String& rMemName = rMembers[j]->GetString(); + if (pDim->GetExistingMemberByName(rMemName)) + // this member instance already exists. nothing to do. + continue; + + auto_ptr<ScDPSaveMember> pNewMember(new ScDPSaveMember(rMemName)); + pNewMember->SetIsVisible(true); + pDim->AddMember(pNewMember.release()); + } + } + + mbDimensionMembersBuilt = true; +} + diff --git a/sc/source/core/data/dptabres.cxx b/sc/source/core/data/dptabres.cxx index 398d4d1c7e01..07a783bdb2b1 100644 --- a/sc/source/core/data/dptabres.cxx +++ b/sc/source/core/data/dptabres.cxx @@ -67,6 +67,7 @@ using ::std::vector; using ::std::pair; using ::std::hash_map; using ::com::sun::star::uno::Sequence; +using ::rtl::OUString; // ----------------------------------------------------------------------- @@ -825,11 +826,11 @@ USHORT ScDPResultData::GetMeasureRefOrient(long nMeasure) const return pMeasRefOrient[nMeasure]; } -String ScDPResultData::GetMeasureString(long nMeasure, BOOL bForce, ScSubTotalFunc eForceFunc) const +String ScDPResultData::GetMeasureString(long nMeasure, BOOL bForce, ScSubTotalFunc eForceFunc, bool& rbTotalResult) const { // with bForce==TRUE, return function instead of "result" for single measure // with eForceFunc != SUBTOTAL_FUNC_NONE, always use eForceFunc - + rbTotalResult = false; if ( nMeasure < 0 || ( nMeasCount == 1 && !bForce && eForceFunc == SUBTOTAL_FUNC_NONE ) ) { // for user-specified subtotal function with all measures, @@ -837,12 +838,19 @@ String ScDPResultData::GetMeasureString(long nMeasure, BOOL bForce, ScSubTotalFu if ( eForceFunc != SUBTOTAL_FUNC_NONE ) return ScGlobal::GetRscString(nFuncStrIds[eForceFunc]); + rbTotalResult = true; return ScGlobal::GetRscString(STR_TABLE_ERGEBNIS); } else { DBG_ASSERT( pMeasNames && nMeasure < nMeasCount, "bumm" ); - + ScDPDimension* pDataDim = pSource->GetDataDimension(nMeasure); + if (pDataDim) + { + const OUString* pLayoutName = pDataDim->GetLayoutName(); + if (pLayoutName) + return *pLayoutName; + } String aRet; ScSubTotalFunc eFunc = ( eForceFunc == SUBTOTAL_FUNC_NONE ) ? GetMeasureFunction(nMeasure) : eForceFunc; @@ -896,6 +904,11 @@ BOOL ScDPResultData::HasCommonElement( const ScDPItemData& rFirstData, long nFir return pSource->GetData()->HasCommonElement( rFirstData, nFirstIndex, rSecondData, nSecondIndex ); } +const ScDPSource* ScDPResultData::GetSource() const +{ + return pSource; +} + // ----------------------------------------------------------------------- @@ -1172,6 +1185,25 @@ void ScDPResultMember::ProcessData( const vector<ScDPItemData>& aChildMembers, c } } +/** + * Parse subtotal string and replace all occurrences of '?' with the + * caption string. + */ +static String lcl_parseSubtotalName(const String& rSubStr, const String& rCaption) +{ + String aNewStr; + xub_StrLen n = rSubStr.Len(); + for (xub_StrLen i = 0; i < n; ++i) + { + sal_Unicode c = rSubStr.GetChar(i); + if (c == sal_Unicode('?')) + aNewStr.Append(rCaption); + else + aNewStr.Append(c); + } + return aNewStr; +} + void ScDPResultMember::FillMemberResults( uno::Sequence<sheet::MemberResult>* pSequences, long& rPos, long nMeasure, BOOL bRoot, const String* pMemberName, @@ -1204,17 +1236,25 @@ void ScDPResultMember::FillMemberResults( uno::Sequence<sheet::MemberResult>* pS } String aCaption = aName; + if (pMemberDesc) + { + const OUString* pLayoutName = pMemberDesc->GetLayoutName(); + if (pLayoutName) + { + aCaption = *pLayoutName; + bIsNumeric = false; // layout name is always non-numeric. + } + } + if ( pMemberCaption ) // use pMemberCaption if != NULL aCaption = *pMemberCaption; if (!aCaption.Len()) aCaption = ScGlobal::GetRscString(STR_EMPTYDATA); - if ( !bIsNumeric ) - { - // add a "'" character so a string isn't parsed as value in the output cell - //! have a separate bit in Flags (MemberResultFlags) instead? - aCaption.Insert( (sal_Unicode) '\'', 0 ); - } + if (bIsNumeric) + pArray[rPos].Flags |= sheet::MemberResultFlags::NUMERIC; + else + pArray[rPos].Flags &= ~sheet::MemberResultFlags::NUMERIC; if ( nSize && !bRoot ) // root is overwritten by first dimension { @@ -1277,9 +1317,30 @@ void ScDPResultMember::FillMemberResults( uno::Sequence<sheet::MemberResult>* pS if (bHasChild) eForce = lcl_GetForceFunc( pParentLevel, nUserPos ); - String aSubStr = aName; //! caption? + bool bTotalResult = false; + String aSubStr = aCaption; aSubStr += ' '; - aSubStr += pResultData->GetMeasureString(nMemberMeasure, FALSE, eForce); + aSubStr += pResultData->GetMeasureString(nMemberMeasure, FALSE, eForce, bTotalResult); + + if (bTotalResult) + { + if (pMemberDesc) + { + // single data field layout. + const OUString* pSubtotalName = pParentDim->GetSubtotalName(); + if (pSubtotalName) + aSubStr = lcl_parseSubtotalName(*pSubtotalName, aCaption); + pArray[rPos].Flags &= ~sheet::MemberResultFlags::GRANDTOTAL; + } + else + { + // root member - subtotal (grand total?) for multi-data field layout. + const rtl::OUString* pGrandTotalName = pResultData->GetSource()->GetGrandTotalName(); + if (pGrandTotalName) + aSubStr = *pGrandTotalName; + pArray[rPos].Flags |= sheet::MemberResultFlags::GRANDTOTAL; + } + } pArray[rPos].Name = rtl::OUString(aName); pArray[rPos].Caption = rtl::OUString(aSubStr); @@ -2796,8 +2857,9 @@ void ScDPResultDimension::FillMemberResults( uno::Sequence<sheet::MemberResult>* // in data layout dimension, use first member with different measures/names if ( bIsDataLayout ) { + bool bTotalResult = false; String aMbrName = pResultData->GetMeasureDimensionName( nSorted ); - String aMbrCapt = pResultData->GetMeasureString( nSorted, FALSE, SUBTOTAL_FUNC_NONE ); + String aMbrCapt = pResultData->GetMeasureString( nSorted, FALSE, SUBTOTAL_FUNC_NONE, bTotalResult ); maMemberArray[0]->FillMemberResults( pSequences, nPos, nSorted, FALSE, &aMbrName, &aMbrCapt ); } else if ( pMember->IsVisible() ) diff --git a/sc/source/core/data/dptabsrc.cxx b/sc/source/core/data/dptabsrc.cxx index 5fa5c393df37..bc1394307f26 100644 --- a/sc/source/core/data/dptabsrc.cxx +++ b/sc/source/core/data/dptabsrc.cxx @@ -85,6 +85,7 @@ using ::com::sun::star::uno::Reference; using ::com::sun::star::uno::Sequence; using ::com::sun::star::uno::Any; using ::com::sun::star::sheet::DataPilotFieldAutoShowInfo; +using ::rtl::OUString; // ----------------------------------------------------------------------- @@ -141,15 +142,14 @@ ScDPSource::ScDPSource( ScDPTableData* pD ) : pRowResRoot( NULL ), pColResults( NULL ), pRowResults( NULL ), - bResultOverflow( FALSE ) + bResultOverflow( FALSE ), + mpGrandTotalName(NULL) { pData->SetEmptyFlags( bIgnoreEmptyRows, bRepeatIfEmpty ); } ScDPSource::~ScDPSource() { - delete pData; // ScDPTableData is not ref-counted - if (pDimensions) pDimensions->release(); // ref-counted @@ -163,6 +163,16 @@ ScDPSource::~ScDPSource() delete pResData; } +void ScDPSource::SetGrandTotalName(const ::rtl::OUString& rName) +{ + mpGrandTotalName.reset(new ::rtl::OUString(rName)); +} + +const ::rtl::OUString* ScDPSource::GetGrandTotalName() const +{ + return mpGrandTotalName.get(); +} + USHORT ScDPSource::GetOrientation(long nColumn) { long i; @@ -186,16 +196,21 @@ long ScDPSource::GetDataDimensionCount() return nDataDimCount; } +ScDPDimension* ScDPSource::GetDataDimension(long nIndex) +{ + if (nIndex < 0 || nIndex >= nDataDimCount) + return NULL; + + long nDimIndex = nDataDims[nIndex]; + return GetDimensionsObject()->getByIndex(nDimIndex); +} + String ScDPSource::GetDataDimName( long nIndex ) { String aRet; - if ( nIndex >= 0 && nIndex < nDataDimCount ) - { - long nDimIndex = nDataDims[nIndex]; - ScDPDimension* pDim = GetDimensionsObject()->getByIndex(nDimIndex); - if (pDim) - aRet = String( pDim->getName() ); - } + ScDPDimension* pDim = GetDataDimension(nIndex); + if (pDim) + aRet = String(pDim->getName()); return aRet; } @@ -488,7 +503,10 @@ String ScDPSource::getDataDescription() String aRet; if ( pResData->GetMeasureCount() == 1 ) - aRet = pResData->GetMeasureString( 0, TRUE, SUBTOTAL_FUNC_NONE ); + { + bool bTotalResult = false; + aRet = pResData->GetMeasureString( 0, TRUE, SUBTOTAL_FUNC_NONE, bTotalResult ); + } // empty for more than one measure @@ -1132,6 +1150,7 @@ uno::Reference<beans::XPropertySetInfo> SAL_CALL ScDPSource::getPropertySetInfo( throw(uno::RuntimeException) { ScUnoGuard aGuard; + using beans::PropertyAttribute::READONLY; static SfxItemPropertyMapEntry aDPSourceMap_Impl[] = { @@ -1140,6 +1159,10 @@ uno::Reference<beans::XPropertySetInfo> SAL_CALL ScDPSource::getPropertySetInfo( {MAP_CHAR_LEN(SC_UNO_IGNOREEM), 0, &getBooleanCppuType(), 0, 0 }, // for sheet data only {MAP_CHAR_LEN(SC_UNO_REPEATIF), 0, &getBooleanCppuType(), 0, 0 }, // for sheet data only {MAP_CHAR_LEN(SC_UNO_ROWGRAND), 0, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_ROWFIELDCOUNT), 0, &getCppuType(static_cast<sal_Int32*>(0)), READONLY, 0 }, + {MAP_CHAR_LEN(SC_UNO_COLUMNFIELDCOUNT), 0, &getCppuType(static_cast<sal_Int32*>(0)), READONLY, 0 }, + {MAP_CHAR_LEN(SC_UNO_DATAFIELDCOUNT), 0, &getCppuType(static_cast<sal_Int32*>(0)), READONLY, 0 }, + {MAP_CHAR_LEN(SC_UNO_GRANDTOTAL_NAME), 0, &getCppuType(static_cast<OUString*>(0)), 0, 0 }, {0,0,0,0,0,0} }; static uno::Reference<beans::XPropertySetInfo> aRef = @@ -1161,6 +1184,12 @@ void SAL_CALL ScDPSource::setPropertyValue( const rtl::OUString& aPropertyName, setIgnoreEmptyRows( lcl_GetBoolFromAny( aValue ) ); else if ( aNameStr.EqualsAscii( SC_UNO_REPEATIF ) ) setRepeatIfEmpty( lcl_GetBoolFromAny( aValue ) ); + else if (aNameStr.EqualsAscii(SC_UNO_GRANDTOTAL_NAME)) + { + OUString aName; + if (aValue >>= aName) + mpGrandTotalName.reset(new OUString(aName)); + } else { DBG_ERROR("unknown property"); @@ -1190,6 +1219,11 @@ uno::Any SAL_CALL ScDPSource::getPropertyValue( const rtl::OUString& aPropertyNa aRet <<= static_cast<sal_Int32>(nColDimCount); else if ( aNameStr.EqualsAscii( SC_UNO_DATAFIELDCOUNT ) ) // read-only aRet <<= static_cast<sal_Int32>(nDataDimCount); + else if (aNameStr.EqualsAscii(SC_UNO_GRANDTOTAL_NAME)) + { + if (mpGrandTotalName.get()) + aRet <<= *mpGrandTotalName; + } else { DBG_ERROR("unknown property"); @@ -1337,6 +1371,8 @@ ScDPDimension::ScDPDimension( ScDPSource* pSrc, long nD ) : pHierarchies( NULL ), nUsedHier( 0 ), nFunction( SUBTOTAL_FUNC_SUM ), // sum is default + mpLayoutName(NULL), + mpSubtotalName(NULL), nSourceDim( -1 ), bHasSelectedPage( FALSE ), pSelectedData( NULL ) @@ -1364,6 +1400,16 @@ ScDPHierarchies* ScDPDimension::GetHierarchiesObject() return pHierarchies; } +const rtl::OUString* ScDPDimension::GetLayoutName() const +{ + return mpLayoutName.get(); +} + +const rtl::OUString* ScDPDimension::GetSubtotalName() const +{ + return mpSubtotalName.get(); +} + uno::Reference<container::XNameAccess> SAL_CALL ScDPDimension::getHierarchies() throw(uno::RuntimeException) { @@ -1523,6 +1569,8 @@ uno::Reference<beans::XPropertySetInfo> SAL_CALL ScDPDimension::getPropertySetIn {MAP_CHAR_LEN(SC_UNO_POSITION), 0, &getCppuType((sal_Int32*)0), 0, 0 }, {MAP_CHAR_LEN(SC_UNO_REFVALUE), 0, &getCppuType((sheet::DataPilotFieldReference*)0), 0, 0 }, {MAP_CHAR_LEN(SC_UNO_USEDHIER), 0, &getCppuType((sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_LAYOUTNAME), 0, &getCppuType(static_cast<rtl::OUString*>(0)), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_FIELD_SUBTOTALNAME), 0, &getCppuType(static_cast<rtl::OUString*>(0)), 0, 0 }, {0,0,0,0,0,0} }; static uno::Reference<beans::XPropertySetInfo> aRef = @@ -1593,6 +1641,18 @@ void SAL_CALL ScDPDimension::setPropertyValue( const rtl::OUString& aPropertyNam } DELETEZ( pSelectedData ); // invalid after changing aSelectedPage } + else if (aNameStr.EqualsAscii(SC_UNO_LAYOUTNAME)) + { + OUString aTmpName; + if (aValue >>= aTmpName) + mpLayoutName.reset(new OUString(aTmpName)); + } + else if (aNameStr.EqualsAscii(SC_UNO_FIELD_SUBTOTALNAME)) + { + OUString aTmpName; + if (aValue >>= aTmpName) + mpSubtotalName.reset(new OUString(aTmpName)); + } else { DBG_ERROR("unknown property"); @@ -1652,6 +1712,10 @@ uno::Any SAL_CALL ScDPDimension::getPropertyValue( const rtl::OUString& aPropert else aRet <<= uno::Sequence<sheet::TableFilterField>(0); } + else if (aNameStr.EqualsAscii(SC_UNO_LAYOUTNAME)) + aRet <<= mpLayoutName.get() ? *mpLayoutName : OUString::createFromAscii(""); + else if (aNameStr.EqualsAscii(SC_UNO_FIELD_SUBTOTALNAME)) + aRet <<= mpSubtotalName.get() ? *mpSubtotalName : OUString::createFromAscii(""); else { DBG_ERROR("unknown property"); @@ -2155,7 +2219,11 @@ uno::Sequence<sheet::MemberResult> SAL_CALL ScDPLevel::getResults() throw(uno::R return aRet; } - return pSource->GetData()->getDimensionName( nSrcDim ); // (original) dimension name + ScDPDimension* pDim = pSource->GetDimensionsObject()->getByIndex(nSrcDim); + if (!pDim) + return rtl::OUString(); + + return pDim->getName(); } void SAL_CALL ScDPLevel::setName( const ::rtl::OUString& /* rNewName */ ) throw(uno::RuntimeException) @@ -2258,6 +2326,20 @@ uno::Any SAL_CALL ScDPLevel::getPropertyValue( const rtl::OUString& aPropertyNam aRet <<= aAutoShowInfo; else if ( aNameStr.EqualsAscii( SC_UNO_LAYOUT ) ) aRet <<= aLayoutInfo; + else if (aNameStr.EqualsAscii(SC_UNO_LAYOUTNAME)) + { + // read only property + long nSrcDim = pSource->GetSourceDim(nDim); + ScDPDimension* pDim = pSource->GetDimensionsObject()->getByIndex(nSrcDim); + if (!pDim) + return aRet; + + const OUString* pLayoutName = pDim->GetLayoutName(); + if (!pLayoutName) + return aRet; + + aRet <<= *pLayoutName; + } else { DBG_ERROR("unknown property"); @@ -2550,6 +2632,7 @@ ScDPMember::ScDPMember( ScDPSource* pSrc, long nD, long nH, long nL, nHier( nH ), nLev( nL ), maData( rN, fV, bHV ), + mpLayoutName(NULL), nPosition( -1 ), bVisible( TRUE ), bShowDet( TRUE ) @@ -2610,6 +2693,11 @@ void ScDPMember::FillItemData( ScDPItemData& rData ) const rData = maData; } +const OUString* ScDPMember::GetLayoutName() const +{ + return mpLayoutName.get(); +} + String ScDPMember::GetNameStr() const { return maData.aString; @@ -2669,6 +2757,7 @@ uno::Reference<beans::XPropertySetInfo> SAL_CALL ScDPMember::getPropertySetInfo( {MAP_CHAR_LEN(SC_UNO_ISVISIBL), 0, &getBooleanCppuType(), 0, 0 }, {MAP_CHAR_LEN(SC_UNO_POSITION), 0, &getCppuType((sal_Int32*)0), 0, 0 }, {MAP_CHAR_LEN(SC_UNO_SHOWDETA), 0, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_LAYOUTNAME), 0, &getCppuType(static_cast<rtl::OUString*>(0)), 0, 0 }, {0,0,0,0,0,0} }; static uno::Reference<beans::XPropertySetInfo> aRef = @@ -2692,6 +2781,12 @@ void SAL_CALL ScDPMember::setPropertyValue( const rtl::OUString& aPropertyName, if (aValue >>= nInt) setPosition( nInt ); } + else if (aNameStr.EqualsAscii(SC_UNO_LAYOUTNAME)) + { + rtl::OUString aName; + if (aValue >>= aName) + mpLayoutName.reset(new rtl::OUString(aName)); + } else { DBG_ERROR("unknown property"); @@ -2711,6 +2806,8 @@ uno::Any SAL_CALL ScDPMember::getPropertyValue( const rtl::OUString& aPropertyNa lcl_SetBoolInAny( aRet, getShowDetails() ); else if ( aNameStr.EqualsAscii( SC_UNO_POSITION ) ) aRet <<= (sal_Int32) getPosition(); + else if (aNameStr.EqualsAscii(SC_UNO_LAYOUTNAME)) + aRet <<= mpLayoutName.get() ? *mpLayoutName : rtl::OUString(); else { DBG_ERROR("unknown property"); diff --git a/sc/source/filter/excel/read.cxx b/sc/source/filter/excel/read.cxx index d1ae00376cde..f87c12f8c26d 100644 --- a/sc/source/filter/excel/read.cxx +++ b/sc/source/filter/excel/read.cxx @@ -1178,6 +1178,9 @@ FltError ImportExcel8::Read( void ) eLastErr = SCWARN_IMPORT_ROW_OVERFLOW; else if( rAddrConv.IsColTruncated() ) eLastErr = SCWARN_IMPORT_COLUMN_OVERFLOW; + + if( GetBiff() == EXC_BIFF8 ) + GetPivotTableManager().MaybeRefreshPivotTables(); } return eLastErr; diff --git a/sc/source/filter/excel/xepivot.cxx b/sc/source/filter/excel/xepivot.cxx index 0b10ded5aa9e..78bc0e0b2f99 100644 --- a/sc/source/filter/excel/xepivot.cxx +++ b/sc/source/filter/excel/xepivot.cxx @@ -67,6 +67,7 @@ using ::com::sun::star::sheet::DataPilotFieldSortInfo; using ::com::sun::star::sheet::DataPilotFieldAutoShowInfo; using ::com::sun::star::sheet::DataPilotFieldLayoutInfo; using ::com::sun::star::sheet::DataPilotFieldReference; +using ::rtl::OUString; using ::rtl::OString; using ::rtl::OUString; @@ -972,6 +973,11 @@ void XclExpPTItem::SetPropertiesFromMember( const ScDPSaveMember& rSaveMem ) { ::set_flag( maItemInfo.mnFlags, EXC_SXVI_HIDDEN, !rSaveMem.GetIsVisible() ); ::set_flag( maItemInfo.mnFlags, EXC_SXVI_HIDEDETAIL, !rSaveMem.GetShowDetails() ); + + // visible name + const OUString* pVisName = rSaveMem.GetLayoutName(); + if (pVisName && !pVisName->equals(GetItemName())) + maItemInfo.SetVisName(*pVisName); } void XclExpPTItem::WriteBody( XclExpStream& rStrm ) @@ -1040,8 +1046,13 @@ void XclExpPTField::SetPropertiesFromDim( const ScDPSaveDimension& rSaveDim ) ::set_flag( maFieldExtInfo.mnFlags, EXC_SXVDEX_SHOWALL, rSaveDim.GetShowEmpty() ); // visible name - if( rSaveDim.HasLayoutName() && (rSaveDim.GetLayoutName() != GetFieldName()) ) - maFieldInfo.SetVisName( rSaveDim.GetLayoutName() ); + const OUString* pLayoutName = rSaveDim.GetLayoutName(); + if (pLayoutName && !pLayoutName->equals(GetFieldName())) + maFieldInfo.SetVisName(*pLayoutName); + + const rtl::OUString* pSubtotalName = rSaveDim.GetSubtotalName(); + if (pSubtotalName) + maFieldExtInfo.mpFieldTotalName.reset(new rtl::OUString(*pSubtotalName)); // subtotals XclPTSubtotalVec aSubtotals; @@ -1108,7 +1119,11 @@ void XclExpPTField::SetDataPropertiesFromDim( const ScDPSaveDimension& rSaveDim rDataInfo.SetApiAggFunc( eFunc ); // visible name - rDataInfo.SetVisName( lclGetDataFieldCaption( GetFieldName(), eFunc ) ); + const rtl::OUString* pVisName = rSaveDim.GetLayoutName(); + if (pVisName) + rDataInfo.SetVisName(*pVisName); + else + rDataInfo.SetVisName( lclGetDataFieldCaption( GetFieldName(), eFunc ) ); // result field reference if( const DataPilotFieldReference* pFieldRef = rSaveDim.GetReferenceValue() ) @@ -1217,10 +1232,9 @@ XclExpPivotTable::XclExpPivotTable( const XclExpRoot& rRoot, const ScDPObject& r // pivot table properties from DP object mnOutScTab = rOutScRange.aStart.Tab(); maPTInfo.maTableName = rDPObj.GetName(); - maPTInfo.maDataName = ScGlobal::GetRscString( STR_PIVOT_DATA ); maPTInfo.mnCacheIdx = mrPCache.GetCacheIndex(); - maPTAutoFormat.Init( rDPObj ); + maPTViewEx9Info.Init( rDPObj ); if( const ScDPSaveData* pSaveData = rDPObj.GetSaveData() ) { @@ -1301,8 +1315,10 @@ void XclExpPivotTable::Save( XclExpStream& rStrm ) WriteSxli( rStrm, maPTInfo.mnDataCols, maPTInfo.mnColFields ); // SXEX WriteSxex( rStrm ); - // SX_AUTOFORMAT - WriteSxAutoformat( rStrm ); + // QSISXTAG + WriteQsiSxTag( rStrm ); + // SXVIEWEX9 + WriteSxViewEx9( rStrm ); } } @@ -1336,6 +1352,15 @@ void XclExpPivotTable::SetPropertiesFromDP( const ScDPSaveData& rSaveData ) ::set_flag( maPTInfo.mnFlags, EXC_SXVIEW_COLGRAND, rSaveData.GetColumnGrand() ); ::set_flag( maPTExtInfo.mnFlags, EXC_SXEX_DRILLDOWN, rSaveData.GetDrillDown() ); mbFilterBtn = rSaveData.GetFilterButton(); + const ScDPSaveDimension* pDim = rSaveData.GetExistingDataLayoutDimension(); + if (!pDim) + return; + + const rtl::OUString* pLayoutName = pDim->GetLayoutName(); + if (pLayoutName) + maPTInfo.maDataName = *pLayoutName; + else + maPTInfo.maDataName = ScGlobal::GetRscString(STR_PIVOT_DATA); } void XclExpPivotTable::SetFieldPropertiesFromDim( const ScDPSaveDimension& rSaveDim ) @@ -1443,17 +1468,21 @@ void XclExpPivotTable::Finalize() rnDataXclRow = rnXclRow1 + maPTInfo.mnColFields + 1; if( maDataFields.empty() ) ++rnDataXclRow; - if( 0 == maPTAutoFormat.mnGridLayout ) + + bool bExtraHeaderRow = (0 == maPTViewEx9Info.mnGridLayout && maPTInfo.mnColFields == 0); + if (bExtraHeaderRow) + // Insert an extra row only when there is no column field. ++rnDataXclRow; + rnXclCol2 = ::std::max( rnXclCol2, rnDataXclCol ); rnXclRow2 = ::std::max( rnXclRow2, rnDataXclRow ); maPTInfo.mnDataCols = rnXclCol2 - rnDataXclCol + 1; maPTInfo.mnDataRows = rnXclRow2 - rnDataXclRow + 1; // first heading - maPTInfo.mnFirstHeadRow = rnXclRow1 + 1; - if( 0 == maPTAutoFormat.mnGridLayout ) - maPTInfo.mnFirstHeadRow++; + maPTInfo.mnFirstHeadRow = rnXclRow1; + if (bExtraHeaderRow) + maPTInfo.mnFirstHeadRow += 2; } // records ---------------------------------------------------------------- @@ -1533,14 +1562,68 @@ void XclExpPivotTable::WriteSxex( XclExpStream& rStrm ) const rStrm.EndRecord(); } -void XclExpPivotTable::WriteSxAutoformat( XclExpStream& rStrm ) const +void XclExpPivotTable::WriteQsiSxTag( XclExpStream& rStrm ) const +{ + rStrm.StartRecord( 0x0802, 32 ); + + sal_uInt16 nRecordType = 0x0802; + sal_uInt16 nDummyFlags = 0x0000; + sal_uInt16 nTableType = 1; // 0 = query table : 1 = pivot table + + rStrm << nRecordType << nDummyFlags << nTableType; + + // General flags + bool bEnableRefresh = true; + bool bPCacheInvalid = false; + bool bOlapPTReport = false; + + sal_uInt16 nFlags = 0x0000; + if (bEnableRefresh) nFlags |= 0x0001; + if (bPCacheInvalid) nFlags |= 0x0002; + if (bOlapPTReport) nFlags |= 0x0004; + rStrm << nFlags; + + // Feature-specific options. The value differs depending on the table + // type, but we assume the table type is always pivot table. + sal_uInt32 nOptions = 0x00000000; + bool bNoStencil = false; + bool bHideTotal = false; + bool bEmptyRows = false; + bool bEmptyCols = false; + if (bNoStencil) nOptions |= 0x00000001; + if (bHideTotal) nOptions |= 0x00000002; + if (bEmptyRows) nOptions |= 0x00000008; + if (bEmptyCols) nOptions |= 0x00000010; + rStrm << nOptions; + + enum ExcelVersion + { + Excel2000 = 0, + ExcelXP = 1, + Excel2003 = 2, + Excel2007 = 3 + }; + ExcelVersion eXclVer = Excel2000; + sal_uInt8 nOffsetBytes = 16; + rStrm << static_cast<sal_uInt8>(eXclVer) // version table last refreshed + << static_cast<sal_uInt8>(eXclVer) // minimum version to refresh + << nOffsetBytes + << static_cast<sal_uInt8>(eXclVer); // first version created + + rStrm << XclExpString(maPTInfo.maTableName); + rStrm << static_cast<sal_uInt16>(0x0001); // no idea what this is for. + + rStrm.EndRecord(); +} + +void XclExpPivotTable::WriteSxViewEx9( XclExpStream& rStrm ) const { // Until we sync the autoformat ids only export if using grid header layout // That could only have been set via xls import so far. - if ( 0 == maPTAutoFormat.mnGridLayout ) + if ( 0 == maPTViewEx9Info.mnGridLayout ) { rStrm.StartRecord( EXC_ID_SXVIEWEX9, 17 ); - rStrm << maPTAutoFormat; + rStrm << maPTViewEx9Info; rStrm.EndRecord(); } } diff --git a/sc/source/filter/excel/xestring.cxx b/sc/source/filter/excel/xestring.cxx index 9af8dbfdd851..b657e3b1f1d0 100644 --- a/sc/source/filter/excel/xestring.cxx +++ b/sc/source/filter/excel/xestring.cxx @@ -423,7 +423,8 @@ void XclExpString::WriteFormats( XclExpStream& rStrm, bool bWriteSize ) const void XclExpString::Write( XclExpStream& rStrm ) const { - WriteHeader( rStrm ); + if (!mbSkipHeader) + WriteHeader( rStrm ); WriteBuffer( rStrm ); if( IsWriteFormats() ) // only in BIFF8 included in string WriteFormats( rStrm ); @@ -589,6 +590,7 @@ void XclExpString::Init( sal_Int32 nCurrLen, XclStrFlags nFlags, sal_uInt16 nMax mbSmartFlags = bBiff8 && ::get_flag( nFlags, EXC_STR_SMARTFLAGS ); mbSkipFormats = ::get_flag( nFlags, EXC_STR_SEPARATEFORMATS ); mbWrapped = false; + mbSkipHeader = ::get_flag( nFlags, EXC_STR_NOHEADER ); mnMaxLen = nMaxLen; SetStrLen( nCurrLen ); diff --git a/sc/source/filter/excel/xipivot.cxx b/sc/source/filter/excel/xipivot.cxx index 495f73d75a68..29e20e52e64a 100644 --- a/sc/source/filter/excel/xipivot.cxx +++ b/sc/source/filter/excel/xipivot.cxx @@ -847,6 +847,11 @@ void XclImpPivotCache::ReadPivotCacheStream( XclImpStream& rStrm ) } } +bool XclImpPivotCache::IsRefreshOnLoad() const +{ + return static_cast<bool>(maPCInfo.mnFlags & 0x0004); +} + // ============================================================================ // Pivot table // ============================================================================ @@ -882,6 +887,8 @@ void XclImpPTItem::ConvertItem( ScDPSaveDimension& rSaveDim ) const ScDPSaveMember& rMember = *rSaveDim.GetMemberByName( *pItemName ); rMember.SetIsVisible( !::get_flag( maItemInfo.mnFlags, EXC_SXVI_HIDDEN ) ); rMember.SetShowDetails( !::get_flag( maItemInfo.mnFlags, EXC_SXVI_HIDEDETAIL ) ); + if (maItemInfo.HasVisName()) + rMember.SetLayoutName(*maItemInfo.GetVisName()); } } @@ -1043,7 +1050,7 @@ ScDPSaveDimension* XclImpPTField::ConvertRCPField( ScDPSaveData& rSaveData ) con // visible name if( const String* pVisName = maFieldInfo.GetVisName() ) if( pVisName->Len() > 0 ) - rSaveDim.SetLayoutName( pVisName ); + rSaveDim.SetLayoutName( *pVisName ); // subtotal function(s) XclPTSubtotalVec aSubtotalVec; @@ -1075,6 +1082,10 @@ ScDPSaveDimension* XclImpPTField::ConvertRCPField( ScDPSaveData& rSaveData ) con // grouping info pCacheField->ConvertGroupField( rSaveData, mrPTable.GetVisFieldNames() ); + // custom subtotal name + if (maFieldExtInfo.mpFieldTotalName.get()) + rSaveDim.SetSubtotalName(*maFieldExtInfo.mpFieldTotalName); + return &rSaveDim; } @@ -1099,7 +1110,7 @@ void XclImpPTField::ConvertDataFieldInfo( ScDPSaveDimension& rSaveDim, const Xcl // visible name if( const String* pVisName = rDataInfo.GetVisName() ) if( pVisName->Len() > 0 ) - rSaveDim.SetLayoutName( pVisName ); + rSaveDim.SetLayoutName( *pVisName ); // aggregation function rSaveDim.SetFunction( static_cast< USHORT >( rDataInfo.GetApiAggFunc() ) ); @@ -1134,7 +1145,8 @@ void XclImpPTField::ConvertItems( ScDPSaveDimension& rSaveDim ) const XclImpPivotTable::XclImpPivotTable( const XclImpRoot& rRoot ) : XclImpRoot( rRoot ), - maDataOrientField( *this, EXC_SXIVD_DATA ) + maDataOrientField( *this, EXC_SXIVD_DATA ), + mpDPObj(NULL) { } @@ -1298,7 +1310,7 @@ void XclImpPivotTable::ReadSxex( XclImpStream& rStrm ) void XclImpPivotTable::ReadSxViewEx9( XclImpStream& rStrm ) { - rStrm >> maPTAutoFormat; + rStrm >> maPTViewEx9Info; } // ---------------------------------------------------------------------------- @@ -1336,11 +1348,14 @@ void XclImpPivotTable::Convert() if( const XclImpPTField* pField = GetField( *aIt ) ) pField->ConvertPageField( aSaveData ); +#if 0 // Why do we do this ??? + // hidden fields for( sal_uInt16 nField = 0, nCount = GetFieldCount(); nField < nCount; ++nField ) if( const XclImpPTField* pField = GetField( nField ) ) if( (pField->GetAxes() & EXC_SXVD_AXIS_ROWCOLPAGE) == 0 ) pField->ConvertHiddenField( aSaveData ); +#endif // data fields for( aIt = maFiltDataFields.begin(), aEnd = maFiltDataFields.end(); aIt != aEnd; ++aIt ) @@ -1364,12 +1379,30 @@ void XclImpPivotTable::Convert() // create the DataPilot ScDPObject* pDPObj = new ScDPObject( GetDocPtr() ); pDPObj->SetName( maPTInfo.maTableName ); + if (maPTInfo.maDataName.Len() > 0) + aSaveData.GetDataLayoutDimension()->SetLayoutName(maPTInfo.maDataName); + + if (maPTViewEx9Info.maGrandTotalName.Len() > 0) + aSaveData.SetGrandTotalName(maPTViewEx9Info.maGrandTotalName); + pDPObj->SetSaveData( aSaveData ); pDPObj->SetSheetDesc( aDesc ); pDPObj->SetOutRange( aOutRange ); pDPObj->SetAlive( TRUE ); - pDPObj->SetHeaderLayout( maPTAutoFormat.mnGridLayout == 0 ); + pDPObj->SetHeaderLayout( maPTViewEx9Info.mnGridLayout == 0 ); + GetDoc().GetDPCollection()->Insert( pDPObj ); + mpDPObj = pDPObj; +} + +void XclImpPivotTable::MaybeRefresh() +{ + if (mpDPObj && mxPCache->IsRefreshOnLoad()) + { + // 'refresh table on load' flag is set. Refresh the table now. Some + // Excel files contain partial table output when this flag is set. + mpDPObj->Output(); + } } // ============================================================================ @@ -1484,85 +1517,10 @@ void XclImpPivotTableManager::ConvertPivotTables() (*aIt)->Convert(); } -// ============================================================================ - -// Pivot table autoformat settings ============================================ - -/** -classic : 10 08 00 00 00 00 00 00 20 00 00 00 01 00 00 00 00 -default : 10 08 00 00 00 00 00 00 20 00 00 00 01 00 00 00 00 -report01 : 10 08 02 00 00 00 00 00 20 00 00 00 00 10 00 00 00 -report02 : 10 08 02 00 00 00 00 00 20 00 00 00 01 10 00 00 00 -report03 : 10 08 02 00 00 00 00 00 20 00 00 00 02 10 00 00 00 -report04 : 10 08 02 00 00 00 00 00 20 00 00 00 03 10 00 00 00 -report05 : 10 08 02 00 00 00 00 00 20 00 00 00 04 10 00 00 00 -report06 : 10 08 02 00 00 00 00 00 20 00 00 00 05 10 00 00 00 -report07 : 10 08 02 00 00 00 00 00 20 00 00 00 06 10 00 00 00 -report08 : 10 08 02 00 00 00 00 00 20 00 00 00 07 10 00 00 00 -report09 : 10 08 02 00 00 00 00 00 20 00 00 00 08 10 00 00 00 -report10 : 10 08 02 00 00 00 00 00 20 00 00 00 09 10 00 00 00 -table01 : 10 08 00 00 00 00 00 00 20 00 00 00 0a 10 00 00 00 -table02 : 10 08 00 00 00 00 00 00 20 00 00 00 0b 10 00 00 00 -table03 : 10 08 00 00 00 00 00 00 20 00 00 00 0c 10 00 00 00 -table04 : 10 08 00 00 00 00 00 00 20 00 00 00 0d 10 00 00 00 -table05 : 10 08 00 00 00 00 00 00 20 00 00 00 0e 10 00 00 00 -table06 : 10 08 00 00 00 00 00 00 20 00 00 00 0f 10 00 00 00 -table07 : 10 08 00 00 00 00 00 00 20 00 00 00 10 10 00 00 00 -table08 : 10 08 00 00 00 00 00 00 20 00 00 00 11 10 00 00 00 -table09 : 10 08 00 00 00 00 00 00 20 00 00 00 12 10 00 00 00 -table10 : 10 08 00 00 00 00 00 00 20 00 00 00 13 10 00 00 00 -none : 10 08 00 00 00 00 00 00 20 00 00 00 15 10 00 00 00 -**/ - -XclPTAutoFormat::XclPTAutoFormat() : - mbReport( 0 ), - mnAutoFormat( 0 ), - mnGridLayout( 0x10 ) -{ -} - -void XclPTAutoFormat::Init( const ScDPObject& rDPObj ) -{ - if( rDPObj.GetHeaderLayout() ) - { - mbReport = 0; - mnAutoFormat = 1; - mnGridLayout = 0; - } - else - { - // Report1 for now - // TODO : sync with autoformat indicies - mbReport = 2; - mnAutoFormat = 1; - mnGridLayout = 0x10; - } -} - -XclImpStream& operator>>( XclImpStream& rStrm, XclPTAutoFormat& rInfo ) -{ - rStrm.Ignore( 2 ); - rStrm >> rInfo.mbReport; /// 2 for report* fmts ? - rStrm.Ignore( 6 ); - sal_uInt8 nDummy; - return rStrm - >> rInfo.mnAutoFormat - >> rInfo.mnGridLayout - >> nDummy >> nDummy >> nDummy; -} - -XclExpStream& operator<<( XclExpStream& rStrm, const XclPTAutoFormat& rInfo ) +void XclImpPivotTableManager::MaybeRefreshPivotTables() { - return rStrm - << EXC_PT_AUTOFMT_HEADER - << rInfo.mbReport - << EXC_PT_AUTOFMT_ZERO - << EXC_PT_AUTOFMT_FLAGS - << rInfo.mnAutoFormat - << rInfo.mnGridLayout - << static_cast<sal_uInt8>(0x00) - << static_cast<sal_uInt8>(0x00) - << static_cast<sal_uInt8>(0x00); + for( XclImpPivotTableVec::iterator aIt = maPTables.begin(), aEnd = maPTables.end(); aIt != aEnd; ++aIt ) + (*aIt)->MaybeRefresh(); } // ============================================================================ diff --git a/sc/source/filter/excel/xlpivot.cxx b/sc/source/filter/excel/xlpivot.cxx index d36950b2494d..8f5d026379d9 100644 --- a/sc/source/filter/excel/xlpivot.cxx +++ b/sc/source/filter/excel/xlpivot.cxx @@ -31,6 +31,7 @@ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_sc.hxx" #include "dpgroup.hxx" +#include "dpsave.hxx" #include "xestream.hxx" #include "xistream.hxx" #include "xestring.hxx" @@ -581,7 +582,9 @@ XclExpStream& operator<<( XclExpStream& rStrm, const XclPTFieldInfo& rInfo ) XclPTFieldExtInfo::XclPTFieldExtInfo() : mnFlags( EXC_SXVDEX_DEFAULTFLAGS ), mnSortField( EXC_SXVDEX_SORT_OWN ), - mnShowField( EXC_SXVDEX_SHOW_NONE ) + mnShowField( EXC_SXVDEX_SHOW_NONE ), + mnNumFmt(0), + mpFieldTotalName(NULL) { } @@ -639,10 +642,19 @@ void XclPTFieldExtInfo::SetApiLayoutMode( sal_Int32 nLayoutMode ) XclImpStream& operator>>( XclImpStream& rStrm, XclPTFieldExtInfo& rInfo ) { - return rStrm - >> rInfo.mnFlags - >> rInfo.mnSortField - >> rInfo.mnShowField; + sal_uInt8 nNameLen = 0; + rStrm >> rInfo.mnFlags + >> rInfo.mnSortField + >> rInfo.mnShowField + >> rInfo.mnNumFmt + >> nNameLen; + + rStrm.Ignore(10); + if (nNameLen != 0xFF) + // Custom field total name is used. Pick it up. + rInfo.mpFieldTotalName.reset(new rtl::OUString(rStrm.ReadUniString(nNameLen, 0))); + + return rStrm; } XclExpStream& operator<<( XclExpStream& rStrm, const XclPTFieldExtInfo& rInfo ) @@ -650,9 +662,23 @@ XclExpStream& operator<<( XclExpStream& rStrm, const XclPTFieldExtInfo& rInfo ) rStrm << rInfo.mnFlags << rInfo.mnSortField << rInfo.mnShowField - << EXC_SXVDEX_FORMAT_NONE - << sal_uInt16( 0xFFFF ); // unknown - rStrm.WriteZeroBytes( 8 ); // unknown + << EXC_SXVDEX_FORMAT_NONE; + + if (rInfo.mpFieldTotalName.get() && rInfo.mpFieldTotalName->getLength() > 0) + { + rtl::OUString aFinalName = *rInfo.mpFieldTotalName; + if (aFinalName.getLength() >= 254) + aFinalName = aFinalName.copy(0, 254); + sal_uInt8 nNameLen = static_cast<sal_uInt8>(aFinalName.getLength()); + rStrm << nNameLen; + rStrm.WriteZeroBytes(10); + rStrm << XclExpString(aFinalName, EXC_STR_NOHEADER); + } + else + { + rStrm << sal_uInt16(0xFFFF); + rStrm.WriteZeroBytes(8); + } return rStrm; } @@ -923,3 +949,86 @@ XclExpStream& operator<<( XclExpStream& rStrm, const XclPTExtInfo& rInfo ) // ============================================================================ +// Pivot table autoformat settings ============================================ + +/** +classic : 10 08 00 00 00 00 00 00 20 00 00 00 01 00 00 00 00 +default : 10 08 00 00 00 00 00 00 20 00 00 00 01 00 00 00 00 +report01 : 10 08 02 00 00 00 00 00 20 00 00 00 00 10 00 00 00 +report02 : 10 08 02 00 00 00 00 00 20 00 00 00 01 10 00 00 00 +report03 : 10 08 02 00 00 00 00 00 20 00 00 00 02 10 00 00 00 +report04 : 10 08 02 00 00 00 00 00 20 00 00 00 03 10 00 00 00 +report05 : 10 08 02 00 00 00 00 00 20 00 00 00 04 10 00 00 00 +report06 : 10 08 02 00 00 00 00 00 20 00 00 00 05 10 00 00 00 +report07 : 10 08 02 00 00 00 00 00 20 00 00 00 06 10 00 00 00 +report08 : 10 08 02 00 00 00 00 00 20 00 00 00 07 10 00 00 00 +report09 : 10 08 02 00 00 00 00 00 20 00 00 00 08 10 00 00 00 +report10 : 10 08 02 00 00 00 00 00 20 00 00 00 09 10 00 00 00 +table01 : 10 08 00 00 00 00 00 00 20 00 00 00 0a 10 00 00 00 +table02 : 10 08 00 00 00 00 00 00 20 00 00 00 0b 10 00 00 00 +table03 : 10 08 00 00 00 00 00 00 20 00 00 00 0c 10 00 00 00 +table04 : 10 08 00 00 00 00 00 00 20 00 00 00 0d 10 00 00 00 +table05 : 10 08 00 00 00 00 00 00 20 00 00 00 0e 10 00 00 00 +table06 : 10 08 00 00 00 00 00 00 20 00 00 00 0f 10 00 00 00 +table07 : 10 08 00 00 00 00 00 00 20 00 00 00 10 10 00 00 00 +table08 : 10 08 00 00 00 00 00 00 20 00 00 00 11 10 00 00 00 +table09 : 10 08 00 00 00 00 00 00 20 00 00 00 12 10 00 00 00 +table10 : 10 08 00 00 00 00 00 00 20 00 00 00 13 10 00 00 00 +none : 10 08 00 00 00 00 00 00 20 00 00 00 15 10 00 00 00 +**/ + +XclPTViewEx9Info::XclPTViewEx9Info() : + mbReport( 0 ), + mnAutoFormat( 0 ), + mnGridLayout( 0x10 ) +{ +} + +void XclPTViewEx9Info::Init( const ScDPObject& rDPObj ) +{ + if( rDPObj.GetHeaderLayout() ) + { + mbReport = 0; + mnAutoFormat = 1; + mnGridLayout = 0; + } + else + { + // Report1 for now + // TODO : sync with autoformat indicies + mbReport = 2; + mnAutoFormat = 1; + mnGridLayout = 0x10; + } + + const ScDPSaveData* pData = rDPObj.GetSaveData(); + if (pData) + { + const rtl::OUString* pGrandTotal = pData->GetGrandTotalName(); + if (pGrandTotal) + maGrandTotalName = *pGrandTotal; + } +} + +XclImpStream& operator>>( XclImpStream& rStrm, XclPTViewEx9Info& rInfo ) +{ + rStrm.Ignore( 2 ); + rStrm >> rInfo.mbReport; /// 2 for report* fmts ? + rStrm.Ignore( 6 ); + rStrm >> rInfo.mnAutoFormat >> rInfo.mnGridLayout; + rInfo.maGrandTotalName = rStrm.ReadUniString(); + return rStrm; +} + +XclExpStream& operator<<( XclExpStream& rStrm, const XclPTViewEx9Info& rInfo ) +{ + return rStrm + << EXC_PT_AUTOFMT_HEADER + << rInfo.mbReport + << EXC_PT_AUTOFMT_ZERO + << EXC_PT_AUTOFMT_FLAGS + << rInfo.mnAutoFormat + << rInfo.mnGridLayout + << XclExpString(rInfo.maGrandTotalName, EXC_STR_DEFAULT, EXC_PT_MAXSTRLEN); +} + diff --git a/sc/source/filter/inc/xepivot.hxx b/sc/source/filter/inc/xepivot.hxx index 67ef2ff6fcd8..e9d2403c29f2 100644 --- a/sc/source/filter/inc/xepivot.hxx +++ b/sc/source/filter/inc/xepivot.hxx @@ -412,8 +412,10 @@ private: void WriteSxli( XclExpStream& rStrm, sal_uInt16 nLineCount, sal_uInt16 nIndexCount ) const; /** Writes the SXEX records containing additional pivot table info. */ void WriteSxex( XclExpStream& rStrm ) const; + + void WriteQsiSxTag( XclExpStream& rStrm ) const; /** Writes the SX_AUTOFORMAT records with the autoformat id and header layout */ - void WriteSxAutoformat( XclExpStream& rStrm ) const; + void WriteSxViewEx9( XclExpStream& rStrm ) const; // ------------------------------------------------------------------------ private: @@ -424,7 +426,7 @@ private: const XclExpPivotCache& mrPCache; /// The pivot cache this pivot table bases on. XclPTInfo maPTInfo; /// Info about the pivot table (SXVIEW record). XclPTExtInfo maPTExtInfo; /// Extended info about the pivot table (SXEX record). - XclPTAutoFormat maPTAutoFormat; /// The selected autoformat (SXVIEWEX9) + XclPTViewEx9Info maPTViewEx9Info; /// The selected autoformat (SXVIEWEX9) XclExpPTFieldList maFieldList; /// All fields in pivot cache order. ScfUInt16Vec maRowFields; /// Row field indexes. ScfUInt16Vec maColFields; /// Column field indexes. diff --git a/sc/source/filter/inc/xestring.hxx b/sc/source/filter/inc/xestring.hxx index 69a1a7af09fb..5fe5e4fb813f 100644 --- a/sc/source/filter/inc/xestring.hxx +++ b/sc/source/filter/inc/xestring.hxx @@ -323,6 +323,7 @@ private: bool mbSmartFlags; /// true = omit flags on empty string; false = always write flags. bool mbSkipFormats; /// true = skip formats on export; false = write complete formatted string. bool mbWrapped; /// true = text contains several paragraphs. + bool mbSkipHeader; /// ture = skip length and flags when writing string bytes. }; inline bool operator==( const XclExpString& rLeft, const XclExpString& rRight ) diff --git a/sc/source/filter/inc/xipivot.hxx b/sc/source/filter/inc/xipivot.hxx index 5a98c0793740..15227b8fb1a3 100644 --- a/sc/source/filter/inc/xipivot.hxx +++ b/sc/source/filter/inc/xipivot.hxx @@ -186,6 +186,8 @@ public: /** Reads the entire pivot cache stream. Uses decrypter from passed stream. */ void ReadPivotCacheStream( XclImpStream& rStrm ); + bool IsRefreshOnLoad() const; + private: typedef ::std::vector< XclImpPCFieldRef > XclImpPCFieldVec; @@ -359,6 +361,8 @@ public: /** Inserts the pivot table into the Calc document. */ void Convert(); + void MaybeRefresh(); + // ------------------------------------------------------------------------ private: typedef ::std::vector< XclImpPTFieldRef > XclImpPTFieldVec; @@ -367,7 +371,7 @@ private: XclPTInfo maPTInfo; /// General info about the pivot table (SXVIEW record). XclPTExtInfo maPTExtInfo; /// Extended info about the pivot table (SXEX record). - XclPTAutoFormat maPTAutoFormat; /// The selected autoformat (SX_AUTOFORMAT) + XclPTViewEx9Info maPTViewEx9Info; /// (SXVIEWEX9 record) XclImpPTFieldVec maFields; /// Vector containing all fields. XclImpPTFieldRef mxCurrField; /// Current field for importing additional info. ScfStringVec maVisFieldNames; /// Vector containing all visible field names. @@ -378,6 +382,7 @@ private: ScfUInt16Vec maFiltDataFields; /// Filtered data field indexes. XclImpPTField maDataOrientField; /// Special data field orientation field. ScRange maOutScRange; /// Output range in the Calc document. + ScDPObject* mpDPObj; }; typedef ScfRef< XclImpPivotTable > XclImpPivotTableRef; @@ -437,6 +442,8 @@ public: /** Inserts all pivot tables into the Calc document. */ void ConvertPivotTables(); + void MaybeRefreshPivotTables(); + private: typedef ::std::vector< XclImpPivotCacheRef > XclImpPivotCacheVec; typedef ::std::vector< XclImpPivotTableRef > XclImpPivotTableVec; diff --git a/sc/source/filter/inc/xlpivot.hxx b/sc/source/filter/inc/xlpivot.hxx index 52251ed62294..3ea464e7b919 100644 --- a/sc/source/filter/inc/xlpivot.hxx +++ b/sc/source/filter/inc/xlpivot.hxx @@ -43,6 +43,8 @@ #include "xladdress.hxx" #include "dpobject.hxx" +#include <memory> + class XclImpStream; class XclExpStream; @@ -671,6 +673,8 @@ struct XclPTFieldExtInfo sal_uInt32 mnFlags; /// Several flags and number of items for AutoShow. sal_uInt16 mnSortField; /// Index to data field sorting bases on. sal_uInt16 mnShowField; /// Index to data field AutoShow bases on. + sal_uInt16 mnNumFmt; + ::std::auto_ptr<rtl::OUString> mpFieldTotalName; explicit XclPTFieldExtInfo(); @@ -796,19 +800,20 @@ XclExpStream& operator<<( XclExpStream& rStrm, const XclPTExtInfo& rInfo ); // Pivot table autoformat settings ============================================== -/** Pivot table autoformat settings (SX_AUTOFORMAT record). */ -struct XclPTAutoFormat +/** Pivot table autoformat settings (SXVIEWEX9 record). */ +struct XclPTViewEx9Info { sal_uInt32 mbReport; /// 2 for report* fmts ? sal_uInt8 mnAutoFormat; /// AutoFormat ID sal_uInt8 mnGridLayout; /// 0 == gridlayout, 0x10 == modern + String maGrandTotalName; - explicit XclPTAutoFormat(); + explicit XclPTViewEx9Info(); void Init( const ScDPObject& rDPObj ); }; -XclImpStream& operator>>( XclImpStream& rStrm, XclPTAutoFormat& rInfo ); -XclExpStream& operator<<( XclExpStream& rStrm, const XclPTAutoFormat& rInfo ); +XclImpStream& operator>>( XclImpStream& rStrm, XclPTViewEx9Info& rInfo ); +XclExpStream& operator<<( XclExpStream& rStrm, const XclPTViewEx9Info& rInfo ); // ============================================================================ #endif diff --git a/sc/source/filter/inc/xlstring.hxx b/sc/source/filter/inc/xlstring.hxx index 0970fafd1ed6..32ee23f83d85 100644 --- a/sc/source/filter/inc/xlstring.hxx +++ b/sc/source/filter/inc/xlstring.hxx @@ -43,6 +43,7 @@ const XclStrFlags EXC_STR_FORCEUNICODE = 0x0001; /// Always use UCS-2 cha const XclStrFlags EXC_STR_8BITLENGTH = 0x0002; /// 8-bit string length field (default: 16-bit). const XclStrFlags EXC_STR_SMARTFLAGS = 0x0004; /// Omit flags on empty string (default: read/write always). BIFF8 only. const XclStrFlags EXC_STR_SEPARATEFORMATS = 0x0008; /// Import: Keep old formats when reading unformatted string (default: clear formats); Export: Write unformatted string. +const XclStrFlags EXC_STR_NOHEADER = 0x0010; /// Export: Don't write the length and flag fields. // ---------------------------------------------------------------------------- diff --git a/sc/source/ui/dbgui/pvfundlg.cxx b/sc/source/ui/dbgui/pvfundlg.cxx index d44791ff6972..dac8ee1e5e04 100644 --- a/sc/source/ui/dbgui/pvfundlg.cxx +++ b/sc/source/ui/dbgui/pvfundlg.cxx @@ -705,7 +705,9 @@ ScDPShowDetailDlg::ScDPShowDetailDlg( Window* pParent, ScDPObject& rDPObj, USHOR maLbDims ( this, ScResId( LB_DIMS ) ), maBtnOk ( this, ScResId( BTN_OK ) ), maBtnCancel ( this, ScResId( BTN_CANCEL ) ), - maBtnHelp ( this, ScResId( BTN_HELP ) ) + maBtnHelp ( this, ScResId( BTN_HELP ) ), + + mrDPObj(rDPObj) { FreeResource(); @@ -719,7 +721,13 @@ ScDPShowDetailDlg::ScDPShowDetailDlg( Window* pParent, ScDPObject& rDPObj, USHOR { const ScDPSaveDimension* pDimension = pSaveData ? pSaveData->GetExistingDimensionByName(aName) : 0; if ( !pDimension || (pDimension->GetOrientation() != nOrient) ) + { + const OUString* pLayoutName = pDimension->GetLayoutName(); + if (pLayoutName) + aName = *pLayoutName; maLbDims.InsertEntry( aName ); + maNameIndexMap.insert(DimNameIndexMap::value_type(aName, nDim)); + } } } if( maLbDims.GetEntryCount() ) @@ -735,7 +743,17 @@ short ScDPShowDetailDlg::Execute() String ScDPShowDetailDlg::GetDimensionName() const { - return maLbDims.GetSelectEntry(); + // Look up the internal dimension name which may be different from the + // displayed field name. + String aSelectedName = maLbDims.GetSelectEntry(); + DimNameIndexMap::const_iterator itr = maNameIndexMap.find(aSelectedName); + if (itr == maNameIndexMap.end()) + // This should never happen! + return aSelectedName; + + long nDim = itr->second; + BOOL bIsDataLayout = false; + return mrDPObj.GetDimName(nDim, bIsDataLayout); } IMPL_LINK( ScDPShowDetailDlg, DblClickHdl, ListBox*, pLBox ) diff --git a/sc/source/ui/dbgui/pvlaydlg.cxx b/sc/source/ui/dbgui/pvlaydlg.cxx index 7b03e067a865..c23068b82200 100644 --- a/sc/source/ui/dbgui/pvlaydlg.cxx +++ b/sc/source/ui/dbgui/pvlaydlg.cxx @@ -63,6 +63,7 @@ #include "sc.hrc" //CHINA001 #include "scabstdlg.hxx" //CHINA001 using namespace com::sun::star; +using ::rtl::OUString; //---------------------------------------------------------------------------- @@ -1491,6 +1492,8 @@ IMPL_LINK( ScDPLayoutDlg, OkHdl, OKButton *, EMPTYARG ) nPageCount, nColCount, nRowCount, nDataCount ); if ( bFit ) { + ScDPSaveData* pOldSaveData = xDlgDPObject->GetSaveData(); + ScRange aOutRange( aAdrDest ); // bToNewTable is passed separately ScDPSaveData aSaveData; @@ -1522,6 +1525,22 @@ IMPL_LINK( ScDPLayoutDlg, OkHdl, OKButton *, EMPTYARG ) pDim->SetSortInfo( &aIt->maSortInfo ); pDim->SetLayoutInfo( &aIt->maLayoutInfo ); pDim->SetAutoShowInfo( &aIt->maShowInfo ); + ScDPSaveDimension* pOldDim = NULL; + if (pOldSaveData) + { + // Transfer the existing layout names to new dimension instance. + pOldDim = pOldSaveData->GetExistingDimensionByName(aIt->maName); + if (pOldDim) + { + const OUString* pLayoutName = pOldDim->GetLayoutName(); + if (pLayoutName) + pDim->SetLayoutName(*pLayoutName); + + const OUString* pSubtotalName = pOldDim->GetSubtotalName(); + if (pSubtotalName) + pDim->SetSubtotalName(*pSubtotalName); + } + } bool bManualSort = ( aIt->maSortInfo.Mode == sheet::DataPilotFieldSortMode::MANUAL ); @@ -1542,11 +1561,33 @@ IMPL_LINK( ScDPLayoutDlg, OkHdl, OKButton *, EMPTYARG ) ScDPSaveMember* pMember = pDim->GetMemberByName( *pItem ); pMember->SetIsVisible( bIsVisible ); pMember->SetShowDetails( bShowDetails ); + if (pOldDim) + { + // Transfer the existing layout name. + ScDPSaveMember* pOldMember = pOldDim->GetMemberByName(*pItem); + if (pOldMember) + { + const OUString* pLayoutName = pOldMember->GetLayoutName(); + if (pLayoutName) + pMember->SetLayoutName(*pLayoutName); + } + } } } } } } + ScDPSaveDimension* pDim = aSaveData.GetDataLayoutDimension(); + if (pDim && pOldSaveData) + { + ScDPSaveDimension* pOldDim = pOldSaveData->GetDataLayoutDimension(); + if (pOldDim) + { + const OUString* pLayoutName = pOldDim->GetLayoutName(); + if (pLayoutName) + pDim->SetLayoutName(*pLayoutName); + } + } USHORT nWhichPivot = SC_MOD()->GetPool().GetWhich( SID_PIVOT_TABLE ); ScPivotItem aOutItem( nWhichPivot, &aSaveData, &aOutRange, bToNewTable ); diff --git a/sc/source/ui/inc/pvfundlg.hxx b/sc/source/ui/inc/pvfundlg.hxx index eeeb9c4094c4..6b9aa62c37a3 100644 --- a/sc/source/ui/inc/pvfundlg.hxx +++ b/sc/source/ui/inc/pvfundlg.hxx @@ -55,6 +55,8 @@ #include <sfx2/itemconnect.hxx> #include "pivot.hxx" +#include <hash_map> + // ============================================================================ typedef sfx::ListBoxWrapper< sal_Int32 > ScDPListBoxWrapper; @@ -217,6 +219,11 @@ public: virtual short Execute(); + /** + * @return String internal name of the selected field. Note that this may + * be different from the name displayed in the dialog if the field + * has a layout name. + */ String GetDimensionName() const; private: @@ -228,6 +235,10 @@ private: OKButton maBtnOk; CancelButton maBtnCancel; HelpButton maBtnHelp; + + typedef ::std::hash_map<String, long, ScStringHashCode> DimNameIndexMap; + DimNameIndexMap maNameIndexMap; + ScDPObject& mrDPObj; }; // ============================================================================ diff --git a/sc/source/ui/unoobj/dapiuno.cxx b/sc/source/ui/unoobj/dapiuno.cxx index c68baf36ba2b..c52921f7c5de 100644 --- a/sc/source/ui/unoobj/dapiuno.cxx +++ b/sc/source/ui/unoobj/dapiuno.cxx @@ -1626,8 +1626,13 @@ OUString SAL_CALL ScDataPilotFieldObj::getName() throw(RuntimeException) if( pDim->IsDataLayout() ) aName = OUString( RTL_CONSTASCII_USTRINGPARAM( SC_DATALAYOUT_NAME ) ); else - aName = pDim->GetLayoutName(); - } + { + const rtl::OUString* pLayoutName = pDim->GetLayoutName(); + if (pLayoutName) + aName = *pLayoutName; + else + aName = pDim->GetName(); + } } return aName; } @@ -1639,7 +1644,7 @@ void SAL_CALL ScDataPilotFieldObj::setName( const OUString& rName ) throw(Runtim if( pDim && !pDim->IsDataLayout() ) { String aName( rName ); - pDim->SetLayoutName( &aName ); + pDim->SetLayoutName(aName); SetDPObject( pDPObj ); } } diff --git a/sc/source/ui/view/dbfunc3.cxx b/sc/source/ui/view/dbfunc3.cxx index 8dcb47c927a2..41a5e9d0e050 100644 --- a/sc/source/ui/view/dbfunc3.cxx +++ b/sc/source/ui/view/dbfunc3.cxx @@ -91,6 +91,10 @@ using ::com::sun::star::uno::Sequence; using ::com::sun::star::uno::Reference; using ::com::sun::star::uno::UNO_QUERY; using ::com::sun::star::beans::XPropertySet; +using ::com::sun::star::container::XNameAccess; +using ::com::sun::star::sheet::XDimensionsSupplier; +using ::rtl::OUString; +using ::rtl::OUStringBuffer; using ::std::auto_ptr; // STATIC DATA ----------------------------------------------------------- @@ -1351,123 +1355,304 @@ void ScDBFunc::UngroupDataPilot() } } +OUString lcl_replaceMemberNameInSubtotal(const OUString& rSubtotal, const OUString& rMemberName) +{ + sal_Int32 n = rSubtotal.getLength(); + const sal_Unicode* p = rSubtotal.getStr(); + OUStringBuffer aBuf, aWordBuf; + for (sal_Int32 i = 0; i < n; ++i) + { + sal_Unicode c = p[i]; + if (c == sal_Unicode(' ')) + { + OUString aWord = aWordBuf.makeStringAndClear(); + if (aWord.equals(rMemberName)) + aBuf.append(sal_Unicode('?')); + else + aBuf.append(aWord); + aBuf.append(c); + } + else + aWordBuf.append(c); + } + + if (aWordBuf.getLength() > 0) + { + OUString aWord = aWordBuf.makeStringAndClear(); + if (aWord.equals(rMemberName)) + aBuf.append(sal_Unicode('?')); + else + aBuf.append(aWord); + } + + return aBuf.makeStringAndClear(); +} + void ScDBFunc::DataPilotInput( const ScAddress& rPos, const String& rString ) { + using namespace ::com::sun::star::sheet; + String aNewName( rString ); ScDocument* pDoc = GetViewData()->GetDocument(); ScDPObject* pDPObj = pDoc->GetDPAtCursor( rPos.Col(), rPos.Row(), rPos.Tab() ); - if ( pDPObj ) + if (!pDPObj) + return; + + String aOldText; + pDoc->GetString( rPos.Col(), rPos.Row(), rPos.Tab(), aOldText ); + + if ( aOldText == rString ) { - String aOldText; - pDoc->GetString( rPos.Col(), rPos.Row(), rPos.Tab(), aOldText ); + // nothing to do: silently exit + return; + } - if ( aOldText == rString ) + USHORT nErrorId = 0; + + pDPObj->BuildAllDimensionMembers(); + ScDPSaveData aData( *pDPObj->GetSaveData() ); + BOOL bChange = FALSE; + + USHORT nOrient = DataPilotFieldOrientation_HIDDEN; + long nField = pDPObj->GetHeaderDim( rPos, nOrient ); + if ( nField >= 0 ) + { + // changing a field title + if ( aData.GetExistingDimensionData() ) { - // nothing to do: silently exit - return; - } + // only group dimensions can be renamed - USHORT nErrorId = 0; + ScDPDimensionSaveData* pDimData = aData.GetDimensionData(); + ScDPSaveGroupDimension* pGroupDim = pDimData->GetNamedGroupDimAcc( aOldText ); + if ( pGroupDim ) + { + // valid name: not empty, no existing dimension (group or other) + if ( rString.Len() && !pDPObj->IsDimNameInUse(rString) ) + { + pGroupDim->Rename( aNewName ); - ScDPSaveData aData( *pDPObj->GetSaveData() ); - BOOL bChange = FALSE; + // also rename in SaveData to preserve the field settings + ScDPSaveDimension* pSaveDim = aData.GetDimensionByName( aOldText ); + pSaveDim->SetName( aNewName ); - USHORT nOrient = sheet::DataPilotFieldOrientation_HIDDEN; - long nField = pDPObj->GetHeaderDim( rPos, nOrient ); - if ( nField >= 0 ) + bChange = TRUE; + } + else + nErrorId = STR_INVALIDNAME; + } + } + else if (nOrient == DataPilotFieldOrientation_COLUMN || nOrient == DataPilotFieldOrientation_ROW) + { + BOOL bDataLayout = false; + String aDimName = pDPObj->GetDimName(nField, bDataLayout); + ScDPSaveDimension* pDim = bDataLayout ? aData.GetDataLayoutDimension() : aData.GetDimensionByName(aDimName); + if (pDim) + { + if (rString.Len()) + { + if (rString.EqualsIgnoreCaseAscii(aDimName)) + { + pDim->RemoveLayoutName(); + bChange = true; + } + else if (!pDPObj->IsDimNameInUse(rString)) + { + pDim->SetLayoutName(rString); + bChange = true; + } + else + nErrorId = STR_INVALIDNAME; + } + else + nErrorId = STR_INVALIDNAME; + } + } + } + else if (pDPObj->IsDataDescriptionCell(rPos)) + { + // There is only one data dimension. + ScDPSaveDimension* pDim = aData.GetFirstDimension(sheet::DataPilotFieldOrientation_DATA); + if (pDim) { - // changing a field title + if (rString.Len()) + { + if (rString.EqualsIgnoreCaseAscii(pDim->GetName())) + { + pDim->RemoveLayoutName(); + bChange = true; + } + else if (!pDPObj->IsDimNameInUse(rString)) + { + pDim->SetLayoutName(rString); + bChange = true; + } + else + nErrorId = STR_INVALIDNAME; + } + else + nErrorId = STR_INVALIDNAME; + } + } + else + { + // This is not a field header. + sheet::DataPilotTableHeaderData aPosData; + pDPObj->GetHeaderPositionData(rPos, aPosData); - if ( aData.GetExistingDimensionData() ) + if ( (aPosData.Flags & MemberResultFlags::HASMEMBER) && aOldText.Len() ) + { + if ( aData.GetExistingDimensionData() && !(aPosData.Flags & MemberResultFlags::SUBTOTAL)) { - // only group dimensions can be renamed + BOOL bIsDataLayout; + String aDimName = pDPObj->GetDimName( aPosData.Dimension, bIsDataLayout ); ScDPDimensionSaveData* pDimData = aData.GetDimensionData(); - ScDPSaveGroupDimension* pGroupDim = pDimData->GetNamedGroupDimAcc( aOldText ); + ScDPSaveGroupDimension* pGroupDim = pDimData->GetNamedGroupDimAcc( aDimName ); if ( pGroupDim ) { - // valid name: not empty, no existing dimension (group or other) - if ( aNewName.Len() && !pDPObj->IsDimNameInUse( aNewName ) ) + // valid name: not empty, no existing group in this dimension + //! ignore case? + if ( aNewName.Len() && !pGroupDim->GetNamedGroup( aNewName ) ) { - pGroupDim->Rename( aNewName ); + ScDPSaveGroupItem* pGroup = pGroupDim->GetNamedGroupAcc( aOldText ); + if ( pGroup ) + pGroup->Rename( aNewName ); // rename the existing group + else + { + // create a new group to replace the automatic group + ScDPSaveGroupItem aGroup( aNewName ); + aGroup.AddElement( aOldText ); + pGroupDim->AddGroupItem( aGroup ); + } - // also rename in SaveData to preserve the field settings - ScDPSaveDimension* pSaveDim = aData.GetDimensionByName( aOldText ); - pSaveDim->SetName( aNewName ); + // in both cases also adjust savedata, to preserve member settings (show details) + ScDPSaveDimension* pSaveDim = aData.GetDimensionByName( aDimName ); + ScDPSaveMember* pSaveMember = pSaveDim->GetExistingMemberByName( aOldText ); + if ( pSaveMember ) + pSaveMember->SetName( aNewName ); bChange = TRUE; } else nErrorId = STR_INVALIDNAME; - } + } } - } - else - { - // renaming a group (item)? - // allow only on the item name itself - not on empty cells, not on subtotals - - sheet::DataPilotTableHeaderData aPosData; - pDPObj->GetHeaderPositionData(rPos, aPosData); - if ( ( aPosData.Flags & sheet::MemberResultFlags::HASMEMBER ) && - ! ( aPosData.Flags & sheet::MemberResultFlags::SUBTOTAL ) && - aOldText.Len() ) + else if ((aPosData.Flags & MemberResultFlags::GRANDTOTAL)) { - if ( aData.GetExistingDimensionData() ) + aData.SetGrandTotalName(rString); + bChange = true; + } + else if (aPosData.Dimension >= 0 && aPosData.MemberName.getLength() > 0) + { + BOOL bDataLayout = false; + String aDimName = pDPObj->GetDimName(static_cast<long>(aPosData.Dimension), bDataLayout); + if (bDataLayout) { - BOOL bIsDataLayout; - String aDimName = pDPObj->GetDimName( aPosData.Dimension, bIsDataLayout ); + // data dimension + do + { + if ((aPosData.Flags & MemberResultFlags::SUBTOTAL)) + break; + + ScDPSaveDimension* pDim = aData.GetDimensionByName(aPosData.MemberName); + if (!pDim) + break; - ScDPDimensionSaveData* pDimData = aData.GetDimensionData(); - ScDPSaveGroupDimension* pGroupDim = pDimData->GetNamedGroupDimAcc( aDimName ); - if ( pGroupDim ) + if (!rString.Len()) + { + nErrorId = STR_INVALIDNAME; + break; + } + + if (aPosData.MemberName.equalsIgnoreAsciiCase(rString)) + { + pDim->RemoveLayoutName(); + bChange = true; + } + else if (!pDPObj->IsDimNameInUse(rString)) + { + pDim->SetLayoutName(rString); + bChange = true; + } + else + nErrorId = STR_INVALIDNAME; + } + while (false); + } + else + { + // field member + do { - // valid name: not empty, no existing group in this dimension - //! ignore case? - if ( aNewName.Len() && !pGroupDim->GetNamedGroup( aNewName ) ) + ScDPSaveDimension* pDim = aData.GetDimensionByName(aDimName); + if (!pDim) + break; + + ScDPSaveMember* pMem = pDim->GetExistingMemberByName(aPosData.MemberName); + if (!pMem) + break; + + if ((aPosData.Flags & MemberResultFlags::SUBTOTAL)) { - ScDPSaveGroupItem* pGroup = pGroupDim->GetNamedGroupAcc( aOldText ); - if ( pGroup ) - pGroup->Rename( aNewName ); // rename the existing group + // Change subtotal only when the table has one data dimension. + if (aData.GetDataDimensionCount() > 1) + break; + + const OUString* pLayoutName = pMem->GetLayoutName(); + String aMemberName; + if (pLayoutName) + aMemberName = *pLayoutName; else - { - // create a new group to replace the automatic group - ScDPSaveGroupItem aGroup( aNewName ); - aGroup.AddElement( aOldText ); - pGroupDim->AddGroupItem( aGroup ); - } + aMemberName = aPosData.MemberName; - // in both cases also adjust savedata, to preserve member settings (show details) - ScDPSaveDimension* pSaveDim = aData.GetDimensionByName( aDimName ); - ScDPSaveMember* pSaveMember = pSaveDim->GetExistingMemberByName( aOldText ); - if ( pSaveMember ) - pSaveMember->SetName( aNewName ); - - bChange = TRUE; + String aNew = lcl_replaceMemberNameInSubtotal(rString, aMemberName); + pDim->SetSubtotalName(aNew); + bChange = true; } else - nErrorId = STR_INVALIDNAME; + { + // Check to make sure the member name isn't + // already used. + if (rString.Len()) + { + if (rString.EqualsIgnoreCaseAscii(pMem->GetName())) + { + pMem->RemoveLayoutName(); + bChange = true; + } + else if (!pDim->IsMemberNameInUse(rString)) + { + pMem->SetLayoutName(rString); + bChange = true; + } + else + nErrorId = STR_INVALIDNAME; + } + else + nErrorId = STR_INVALIDNAME; + } } + while (false); } } } + } - if ( bChange ) - { - // apply changes - ScDBDocFunc aFunc( *GetViewData()->GetDocShell() ); - ScDPObject* pNewObj = new ScDPObject( *pDPObj ); - pNewObj->SetSaveData( aData ); - aFunc.DataPilotUpdate( pDPObj, pNewObj, TRUE, FALSE ); - delete pNewObj; - } - else - { - if ( !nErrorId ) - nErrorId = STR_ERR_DATAPILOT_INPUT; - ErrorMessage( nErrorId ); - } + if ( bChange ) + { + // apply changes + ScDBDocFunc aFunc( *GetViewData()->GetDocShell() ); + ScDPObject* pNewObj = new ScDPObject( *pDPObj ); + pNewObj->SetSaveData( aData ); + aFunc.DataPilotUpdate( pDPObj, pNewObj, TRUE, FALSE ); + delete pNewObj; + } + else + { + if ( !nErrorId ) + nErrorId = STR_ERR_DATAPILOT_INPUT; + ErrorMessage( nErrorId ); } } |