ooo-build r14499 - in trunk: . patches/test scratch/sc-xlsutil/src
- From: kyoshida svn gnome org
- To: svn-commits-list gnome org
- Subject: ooo-build r14499 - in trunk: . patches/test scratch/sc-xlsutil/src
- Date: Thu, 13 Nov 2008 20:59:08 +0000 (UTC)
Author: kyoshida
Date: Thu Nov 13 20:59:07 2008
New Revision: 14499
URL: http://svn.gnome.org/viewvc/ooo-build?rev=14499&view=rev
Log:
2008-11-13 Kohei Yoshida <kyoshida novell com>
* patches/test/calc-dp-custom-names.diff: on-going work to support
custom names in datapilot & properly support hidden items in page
fields.
* scratch/sc-xlsutil/src/record.py: display custom grand total name
even if there is none.
Added:
trunk/patches/test/calc-dp-custom-names.diff
Modified:
trunk/ChangeLog
trunk/scratch/sc-xlsutil/src/record.py
Added: trunk/patches/test/calc-dp-custom-names.diff
==============================================================================
--- (empty file)
+++ trunk/patches/test/calc-dp-custom-names.diff Thu Nov 13 20:59:07 2008
@@ -0,0 +1,1800 @@
+diff --git sc/inc/dpobject.hxx sc/inc/dpobject.hxx
+index cef08cb..8213193 100644
+--- sc/inc/dpobject.hxx
++++ sc/inc/dpobject.hxx
+@@ -38,6 +38,8 @@
+ #include "dpoutput.hxx"
+ #include <com/sun/star/sheet/XDimensionsSupplier.hpp>
+
++#include <memory>
++
+ //------------------------------------------------------------------
+
+ namespace com { namespace sun { namespace star { namespace sheet {
+@@ -98,6 +100,7 @@ private:
+ // settings
+ ScDPSaveData* pSaveData;
+ String aTableName;
++ ::std::auto_ptr<rtl::OUString> mpGrandTotalName;
+ String aTableTag;
+ ScRange aOutRange;
+ ScSheetSourceDesc* pSheetDesc; // for sheet data
+@@ -168,6 +171,9 @@ public:
+ const String& GetName() const { return aTableName; }
+ void SetTag(const String& rNew);
+ const String& GetTag() const { return aTableTag; }
++ void SetGrandTotalName(const ::rtl::OUString& rName);
++ const ::rtl::OUString* GetGrandTotalName() const;
++
+
+ BOOL IsDimNameInUse( const String& rName ) const;
+ String GetDimName( long nDim, BOOL& rIsDataLayout );
+diff --git sc/inc/dpsave.hxx sc/inc/dpsave.hxx
+index 8a42ead..bc49095 100644
+--- sc/inc/dpsave.hxx
++++ sc/inc/dpsave.hxx
+@@ -37,6 +37,7 @@
+ #include "scdllapi.h"
+ #include <hash_map>
+ #include <list>
++#include <memory>
+
+ namespace com { namespace sun { namespace star { namespace sheet {
+ struct DataPilotFieldReference;
+@@ -58,6 +59,7 @@ class ScDPSaveMember
+ {
+ private:
+ String aName;
++ ::std::auto_ptr<String> mpLayoutName; // custom name to be displayed in the table.
+ USHORT nVisibleMode;
+ USHORT nShowDetailsMode;
+
+@@ -79,6 +81,9 @@ public:
+
+ void SetName( const String& rNew ); // used if the source member was renamed (groups)
+
++ void SetLayoutName( const String& rName );
++ const String* GetLayoutName() const;
++
+ void WriteToSource( const com::sun::star::uno::Reference<
+ com::sun::star::uno::XInterface>& xMember,
+ sal_Int32 nPosition );
+@@ -91,8 +96,9 @@ class 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;
+@@ -143,9 +149,11 @@ public:
+ USHORT GetFunction() const { return nFunction; }
+ void SetUsedHierarchy(long nNew);
+ long GetUsedHierarchy() const { return nUsedHierarchy; }
+- void SetLayoutName(const String* pName);
+- const String& GetLayoutName() const;
+- BOOL HasLayoutName() const;
++
++ void SetLayoutName(const ::rtl::OUString& rName);
++ const ::rtl::OUString* GetLayoutName() const;
++ void SetSubtotalName(const ::rtl::OUString& rName);
++ const ::rtl::OUString* GetSubtotalName() const;
+
+ const ::com::sun::star::sheet::DataPilotFieldReference* GetReferenceValue() const { return pReferenceValue; }
+ void SetReferenceValue(const ::com::sun::star::sheet::DataPilotFieldReference* pNew);
+@@ -186,6 +194,7 @@ private:
+ USHORT nRepeatEmptyMode;
+ BOOL bFilterButton; // not passed to DataPilotSource
+ BOOL bDrillDown; // not passed to DataPilotSource
++ ::std::auto_ptr<rtl::OUString> mpDataLayoutName;
+
+ public:
+ ScDPSaveData();
+@@ -213,6 +222,8 @@ public:
+ ScDPSaveDimension* GetInnermostDimension(USHORT nOrientation);
+ long GetDataDimensionCount() const;
+
++ void SetDataLayoutName(const ::rtl::OUString& rName);
++ const ::rtl::OUString* GetDataLayoutName() const;
+
+ void SetPosition( ScDPSaveDimension* pDim, long nNew );
+ void SetColumnGrand( BOOL bSet );
+diff --git sc/inc/dptabres.hxx sc/inc/dptabres.hxx
+index 3fb5ef8..f4a60f9 100644
+--- sc/inc/dptabres.hxx
++++ 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 sc/inc/dptabsrc.hxx sc/inc/dptabsrc.hxx
+index 1afed45..094744a 100644
+--- sc/inc/dptabsrc.hxx
++++ 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,11 +109,8 @@ class ScDPSource : public cppu::WeakImplHelper6<
+ com::sun::star::lang::XServiceInfo >
+ {
+ private:
+- void FillCalcInfo(bool bIsRow, ScDPTableData::CalcInfo& rInfo, bool &bHasAutoShow);
+-
+-private:
+ ScDPTableData* pData; // data source
+- ScDPDimensions* pDimensions; // api objects
++ ScDPDimensions* pDimensions; // api objects
+ // settings:
+ long nColDims[SC_DAPI_MAXFIELDS];
+ long nRowDims[SC_DAPI_MAXFIELDS];
+@@ -139,9 +137,18 @@ private:
+ List aRowLevelList;
+ BOOL bResultOverflow;
+
++ ::std::auto_ptr<rtl::OUString> mpGrandTotalName;
++
+ void CreateRes_Impl();
+ void FillMemberResults();
+ void FillLevelList( USHORT nOrientation, List& rList );
++ void FillCalcInfo(bool bIsRow, ScDPTableData::CalcInfo& rInfo, bool &bHasAutoShow);
++
++ /**
++ * Set visibilities of individual rows in the cache table based on the
++ * page field data.
++ */
++ void FilterCacheTableByPageDimensions();
+
+ void SetDupCount( long nNew );
+
+@@ -152,11 +159,18 @@ public:
+ ScDPTableData* GetData() { return pData; }
+ const ScDPTableData* GetData() const { return pData; }
+
++ void SetGrandTotalName(const ::rtl::OUString& rName);
++ const ::rtl::OUString* GetGrandTotalName() const;
++
++ void SetDataName(const ::rtl::OUString& rName);
++ const ::rtl::OUString* GetDataName() 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();
+@@ -323,6 +337,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"
+@@ -340,6 +356,9 @@ public:
+ ScDPDimension* CreateCloneObject();
+ ScDPHierarchies* GetHierarchiesObject();
+
++ 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 )
+@@ -726,7 +745,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;
+@@ -740,6 +759,7 @@ public:
+ BOOL IsNamedItem( const ScDPItemData& r ) const;
+ String GetNameStr() const;
+ void FillItemData( ScDPItemData& rData ) const;
++ const ::rtl::OUString* GetLayoutName() const;
+
+ sal_Int32 Compare( const ScDPMember& rOther ) const; // visible order
+
+diff --git sc/inc/unonames.hxx sc/inc/unonames.hxx
+index 18c858b..7d1f03e 100644
+--- sc/inc/unonames.hxx
++++ sc/inc/unonames.hxx
+@@ -557,6 +557,8 @@
+ #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"
+
+ // (preliminary:)
+ #define SC_UNO_REFVALUE "ReferenceValue"
+diff --git sc/source/core/data/dpobject.cxx sc/source/core/data/dpobject.cxx
+index 4f49665..1c8257a 100644
+--- sc/source/core/data/dpobject.cxx
++++ sc/source/core/data/dpobject.cxx
+@@ -156,6 +156,7 @@ USHORT lcl_GetDataGetOrientation( const uno::Reference<sheet::XDimensionsSupplie
+ ScDPObject::ScDPObject( ScDocument* pD ) :
+ pDoc( pD ),
+ pSaveData( NULL ),
++ mpGrandTotalName(NULL),
+ pSheetDesc( NULL ),
+ pImpDesc( NULL ),
+ pServDesc( NULL ),
+@@ -174,6 +175,7 @@ ScDPObject::ScDPObject(const ScDPObject& r) :
+ DataObject(),
+ pDoc( r.pDoc ),
+ pSaveData( NULL ),
++ mpGrandTotalName(NULL),
+ aTableName( r.aTableName ),
+ aTableTag( r.aTableTag ),
+ aOutRange( r.aOutRange ),
+@@ -191,6 +193,8 @@ ScDPObject::ScDPObject(const ScDPObject& r) :
+ {
+ if (r.pSaveData)
+ pSaveData = new ScDPSaveData(*r.pSaveData);
++ if (r.mpGrandTotalName.get())
++ mpGrandTotalName.reset(new rtl::OUString(*r.mpGrandTotalName));
+ if (r.pSheetDesc)
+ pSheetDesc = new ScSheetSourceDesc(*r.pSheetDesc);
+ if (r.pImpDesc)
+@@ -339,6 +343,16 @@ void ScDPObject::SetTag(const String& rNew)
+ aTableTag = rNew;
+ }
+
++void ScDPObject::SetGrandTotalName(const ::rtl::OUString& rName)
++{
++ mpGrandTotalName.reset(new ::rtl::OUString(rName));
++}
++
++const rtl::OUString* ScDPObject::GetGrandTotalName() const
++{
++ return mpGrandTotalName.get();
++}
++
+ uno::Reference<sheet::XDimensionsSupplier> ScDPObject::GetSource()
+ {
+ CreateObjects();
+@@ -429,7 +443,11 @@ void ScDPObject::CreateObjects()
+ pData = pGroupData;
+ }
+
+- xSource = new ScDPSource( pData );
++ ScDPSource* pSource = new ScDPSource( pData );
++ if (mpGrandTotalName.get())
++ pSource->SetGrandTotalName(*mpGrandTotalName);
++
++ xSource = pSource;
+ }
+
+ if (pSaveData)
+diff --git sc/source/core/data/dpoutput.cxx sc/source/core/data/dpoutput.cxx
+index 6683028..4223a53 100644
+--- sc/source/core/data/dpoutput.cxx
++++ 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;
+@@ -119,7 +120,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 +446,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 +463,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 +474,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 +485,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 +542,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 );
+@@ -1151,7 +1164,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();
+@@ -1168,10 +1181,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();
+@@ -1209,8 +1227,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 )
+@@ -1761,7 +1778,7 @@ long ScDPOutput::GetHeaderDim( const ScAddress& rPos, USHORT& rOrient )
+
+ // test for row header
+
+- if ( nRow+1 == nDataStartRow && nCol >= nTabStartCol == nCol < nTabStartCol + nRowFieldCount )
++ if ( nRow+1 == nDataStartRow && nCol >= nTabStartCol && nCol < nTabStartCol + nRowFieldCount )
+ {
+ rOrient = sheet::DataPilotFieldOrientation_ROW;
+ long nField = nCol - nTabStartCol;
+diff --git sc/source/core/data/dpsave.cxx sc/source/core/data/dpsave.cxx
+index dbcfe30..7fd8d98 100644
+--- sc/source/core/data/dpsave.cxx
++++ sc/source/core/data/dpsave.cxx
+@@ -60,6 +60,7 @@
+ #include <com/sun/star/util/XCloneable.hpp>
+
+ using namespace com::sun::star;
++using ::rtl::OUString;
+
+ // -----------------------------------------------------------------------
+
+@@ -114,6 +115,7 @@ void lcl_SkipExtra( SvStream& rStream )
+
+ ScDPSaveMember::ScDPSaveMember(const String& rName) :
+ aName( rName ),
++ mpLayoutName(NULL),
+ nVisibleMode( SC_DPSAVEMODE_DONTKNOW ),
+ nShowDetailsMode( SC_DPSAVEMODE_DONTKNOW )
+ {
+@@ -121,9 +123,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 String(*r.mpLayoutName));
+ }
+
+ ScDPSaveMember::ScDPSaveMember(SvStream& rStream)
+@@ -186,6 +191,16 @@ void ScDPSaveMember::SetName( const String& rNew )
+ aName = rNew;
+ }
+
++void ScDPSaveMember::SetLayoutName( const String& rName )
++{
++ mpLayoutName.reset(new String(rName));
++}
++
++const String* ScDPSaveMember::GetLayoutName() const
++{
++ return mpLayoutName.get();
++}
++
+ void ScDPSaveMember::WriteToSource( const uno::Reference<uno::XInterface>& xMember, sal_Int32 nPosition )
+ {
+ // nothing to do?
+@@ -206,6 +221,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
+@@ -224,8 +251,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 ),
+@@ -244,6 +272,7 @@ ScDPSaveDimension::ScDPSaveDimension(const String& rName, BOOL bDataLayout) :
+
+ ScDPSaveDimension::ScDPSaveDimension(const ScDPSaveDimension& r) :
+ aName( r.aName ),
++ mpSubtotalName(NULL),
+ bIsDataLayout( r.bIsDataLayout ),
+ bDupFlag( r.bDupFlag ),
+ nOrientation( r.nOrientation ),
+@@ -284,14 +313,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(SvStream& rStream)
+@@ -334,7 +363,6 @@ ScDPSaveDimension::ScDPSaveDimension(SvStream& rStream)
+ pSortInfo = NULL;
+ pAutoShowInfo = NULL;
+ pLayoutInfo = NULL;
+- pLayoutName = NULL;
+ pSelectedPage = NULL;
+ }
+
+@@ -376,7 +404,6 @@ ScDPSaveDimension::~ScDPSaveDimension()
+ delete pSortInfo;
+ delete pAutoShowInfo;
+ delete pLayoutInfo;
+- delete pLayoutName;
+ delete pSelectedPage;
+ delete [] pSubTotalFuncs;
+ }
+@@ -488,25 +515,24 @@ 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();
++}
++
++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::SetReferenceValue(const sheet::DataPilotFieldReference* pNew)
+@@ -642,6 +668,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 <<= rtl::OUString(*mpLayoutName);
++ xDimProp->setPropertyValue(rtl::OUString::createFromAscii(SC_UNO_LAYOUTNAME), aAny);
++ }
++
++ const OUString* pSubTotalName = GetSubtotalName();
++ if (pSubTotalName)
++ {
++ // Custon 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& )
+ {
+@@ -784,7 +823,8 @@ ScDPSaveData::ScDPSaveData() :
+ nIgnoreEmptyMode( SC_DPSAVEMODE_DONTKNOW ),
+ nRepeatEmptyMode( SC_DPSAVEMODE_DONTKNOW ),
+ bFilterButton( TRUE ),
+- bDrillDown( TRUE )
++ bDrillDown( TRUE ),
++ mpDataLayoutName(NULL)
+ {
+ }
+
+@@ -794,13 +834,17 @@ ScDPSaveData::ScDPSaveData(const ScDPSaveData& r) :
+ nIgnoreEmptyMode( r.nIgnoreEmptyMode ),
+ nRepeatEmptyMode( r.nRepeatEmptyMode ),
+ bFilterButton( r.bFilterButton ),
+- bDrillDown( r.bDrillDown )
++ bDrillDown( r.bDrillDown ),
++ mpDataLayoutName(NULL)
+ {
+ if ( r.pDimensionData )
+ pDimensionData = new ScDPDimensionSaveData( *r.pDimensionData );
+ else
+ pDimensionData = NULL;
+
++ if (r.mpDataLayoutName.get())
++ mpDataLayoutName.reset(new OUString(*r.mpDataLayoutName));
++
+ long nCount = r.aDimList.Count();
+ for (long i=0; i<nCount; i++)
+ {
+@@ -819,6 +863,9 @@ ScDPSaveData& ScDPSaveData::operator= ( const ScDPSaveData& r )
+ else
+ pDimensionData = NULL;
+
++ if (r.mpDataLayoutName.get())
++ mpDataLayoutName.reset(new OUString(*r.mpDataLayoutName));
++
+ nColumnGrandMode = r.nColumnGrandMode;
+ nRowGrandMode = r.nRowGrandMode;
+ nIgnoreEmptyMode = r.nIgnoreEmptyMode;
+@@ -861,6 +908,16 @@ BOOL ScDPSaveData::operator== ( const ScDPSaveData& r ) const
+ if ( !pDimensionData || !r.pDimensionData || !( *pDimensionData == *r.pDimensionData ) )
+ return FALSE;
+
++ if (mpDataLayoutName.get())
++ {
++ if (!r.mpDataLayoutName.get())
++ return false;
++ if (!mpDataLayoutName->equals(*r.mpDataLayoutName))
++ return false;
++ }
++ else if (r.mpDataLayoutName.get())
++ return false;
++
+ ULONG nCount = aDimList.Count();
+ if ( nCount != r.aDimList.Count() )
+ return FALSE;
+@@ -1003,6 +1060,16 @@ long ScDPSaveData::GetDataDimensionCount() const
+ return nDataCount;
+ }
+
++void ScDPSaveData::SetDataLayoutName(const OUString& rName)
++{
++ mpDataLayoutName.reset(new OUString(rName));
++}
++
++const OUString* ScDPSaveData::GetDataLayoutName() const
++{
++ return mpDataLayoutName.get();
++}
++
+ void ScDPSaveData::SetPosition( ScDPSaveDimension* pDim, long nNew )
+ {
+ // position (nNew) is counted within dimensions of the same orientation
+diff --git sc/source/core/data/dptabres.cxx sc/source/core/data/dptabres.cxx
+index c52139c..dab5547 100644
+--- sc/source/core/data/dptabres.cxx
++++ 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;
++}
++
+ // -----------------------------------------------------------------------
+
+
+@@ -1204,6 +1217,13 @@ void ScDPResultMember::FillMemberResults( uno::Sequence<sheet::MemberResult>* pS
+ }
+
+ String aCaption = aName;
++ if (pMemberDesc)
++ {
++ const OUString* pLayoutName = pMemberDesc->GetLayoutName();
++ if (pLayoutName)
++ aCaption = *pLayoutName;
++ }
++
+ if ( pMemberCaption ) // use pMemberCaption if != NULL
+ aCaption = *pMemberCaption;
+ if (!aCaption.Len())
+@@ -1277,9 +1297,39 @@ void ScDPResultMember::FillMemberResults( uno::Sequence<sheet::MemberResult>* pS
+ if (bHasChild)
+ eForce = lcl_GetForceFunc( pParentLevel, nUserPos );
+
++ bool bTotalResult = false;
+ String aSubStr = aName; //! caption?
+ 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 = *pSubtotalName;
++ xub_StrLen nPos = aSubStr.Search('?');
++ if (nPos != STRING_NOTFOUND)
++ {
++ String aNew = aSubStr.Copy(0, nPos);
++ aNew += aName;
++ if (nPos+1 < aSubStr.Len())
++ aNew += aSubStr.Copy(nPos+1);
++ aSubStr = aNew;
++ }
++ }
++ }
++ else
++ {
++ // root member - subtotal for multi-data field layout.
++ const rtl::OUString* pGrandTotalName = pResultData->GetSource()->GetGrandTotalName();
++ if (pGrandTotalName)
++ aSubStr = *pGrandTotalName;
++ }
++ }
+
+ pArray[rPos].Name = rtl::OUString(aName);
+ pArray[rPos].Caption = rtl::OUString(aSubStr);
+@@ -2796,8 +2846,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 sc/source/core/data/dptabsrc.cxx sc/source/core/data/dptabsrc.cxx
+index 600eb7b..c5f254e 100644
+--- sc/source/core/data/dptabsrc.cxx
++++ sc/source/core/data/dptabsrc.cxx
+@@ -83,6 +83,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;
+
+ // -----------------------------------------------------------------------
+
+@@ -139,7 +140,8 @@ ScDPSource::ScDPSource( ScDPTableData* pD ) :
+ pRowResRoot( NULL ),
+ pColResults( NULL ),
+ pRowResults( NULL ),
+- bResultOverflow( FALSE )
++ bResultOverflow( FALSE ),
++ mpGrandTotalName(NULL)
+ {
+ pData->SetEmptyFlags( bIgnoreEmptyRows, bRepeatIfEmpty );
+ }
+@@ -161,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;
+@@ -184,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;
+ }
+
+@@ -480,7 +497,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
+
+@@ -685,6 +705,55 @@ void ScDPSource::FillCalcInfo(bool bIsRow, ScDPTableData::CalcInfo& rInfo, bool
+ }
+ }
+
++void ScDPSource::FilterCacheTableByPageDimensions()
++{
++ ScSimpleSharedString& rSharedString = GetData()->GetSharedString();
++
++ // filter table by page dimensions.
++ vector<ScDPCacheTable::Criterion> aCriteria;
++ for (long i = 0; i < nPageDimCount; ++i)
++ {
++ ScDPDimension* pDim = GetDimensionsObject()->getByIndex(nPageDims[i]);
++ long nField = pDim->GetDimension();
++
++ ScDPMembers* pMems = pDim->GetHierarchiesObject()->getByIndex(0)->
++ GetLevelsObject()->getByIndex(0)->GetMembersObject();
++
++ long nMemCount = pMems->getCount();
++ ScDPCacheTable::Criterion aFilter;
++ aFilter.mnFieldIndex = static_cast<sal_Int32>(nField);
++ aFilter.mpFilter.reset(new ScDPCacheTable::GroupFilter(rSharedString));
++ ScDPCacheTable::GroupFilter* pGrpFilter =
++ static_cast<ScDPCacheTable::GroupFilter*>(aFilter.mpFilter.get());
++ for (long j = 0; j < nMemCount; ++j)
++ {
++ ScDPMember* pMem = pMems->getByIndex(j);
++ if (pMem->getIsVisible())
++ {
++ ScDPItemData aData;
++ pMem->FillItemData(aData);
++ pGrpFilter->addMatchItem(aData.aString, aData.fValue, aData.bHasValue);
++ }
++ }
++ if (pGrpFilter->getMatchItemCount() < static_cast<size_t>(nMemCount))
++ // there is at least one invisible item. Add this filter criterion to the mix.
++ aCriteria.push_back(aFilter);
++
++ if (!pDim || !pDim->HasSelectedPage())
++ continue;
++
++ const ScDPItemData& rData = pDim->GetSelectedData();
++ aCriteria.push_back(ScDPCacheTable::Criterion());
++ ScDPCacheTable::Criterion& r = aCriteria.back();
++ r.mnFieldIndex = static_cast<sal_Int32>(nField);
++ sal_Int32 nStrId = rSharedString.getStringId(rData.aString);
++ r.mpFilter.reset(
++ new ScDPCacheTable::SingleFilter(rSharedString, nStrId, rData.fValue, rData.bHasValue));
++ }
++ if (!aCriteria.empty())
++ pData->FilterCacheTable(aCriteria);
++}
++
+ void ScDPSource::CreateRes_Impl()
+ {
+ if ( !pResData )
+@@ -850,29 +919,8 @@ void ScDPSource::CreateRes_Impl()
+ }
+ else
+ {
+- {
+- ScSimpleSharedString& rSharedString = GetData()->GetSharedString();
++ FilterCacheTableByPageDimensions();
+
+- // filter table by page dimensions.
+- vector<ScDPCacheTable::Criterion> aCriteria;
+- for (i = 0; i < nPageDimCount; ++i)
+- {
+- ScDPDimension* pDim = GetDimensionsObject()->getByIndex(nPageDims[i]);
+- if (!pDim || !pDim->HasSelectedPage())
+- continue;
+-
+- long nField = pDim->GetDimension();
+- const ScDPItemData& rData = pDim->GetSelectedData();
+- aCriteria.push_back(ScDPCacheTable::Criterion());
+- ScDPCacheTable::Criterion& r = aCriteria.back();
+- r.mnFieldIndex = static_cast<sal_Int32>(nField);
+- sal_Int32 nStrId = rSharedString.getStringId(rData.aString);
+- r.mpFilter.reset(
+- new ScDPCacheTable::SingleFilter(rSharedString, nStrId, rData.fValue, rData.bHasValue));
+- }
+- if (!aCriteria.empty())
+- pData->FilterCacheTable(aCriteria);
+- }
+ aInfo.aPageDims.reserve(nPageDimCount);
+ for (i = 0; i < nPageDimCount; ++i)
+ aInfo.aPageDims.push_back(nPageDims[i]);
+@@ -1270,6 +1318,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 )
+@@ -1297,6 +1347,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)
+ {
+@@ -1456,6 +1516,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 =
+@@ -1526,6 +1588,18 @@ void SAL_CALL ScDPDimension::setPropertyValue( const rtl::OUString& aPropertyNam
+ }
+ DELETEZ( pSelectedData ); // invalid after changing aSelectedPage
+ }
++ else if (aNameStr.EqualsAscii(SC_UNO_LAYOUTNAME))
++ {
++ OUString aName;
++ if (aValue >>= aName)
++ mpLayoutName.reset(new OUString(aName));
++ }
++ else if (aNameStr.EqualsAscii(SC_UNO_FIELD_SUBTOTALNAME))
++ {
++ OUString aName;
++ if (aValue >>= aName)
++ mpSubtotalName.reset(new OUString(aName));
++ }
+ else
+ {
+ DBG_ERROR("unknown property");
+@@ -1585,6 +1659,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");
+@@ -2085,7 +2163,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)
+@@ -2188,6 +2270,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");
+@@ -2480,6 +2576,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 )
+@@ -2540,6 +2637,11 @@ void ScDPMember::FillItemData( ScDPItemData& rData ) const
+ rData = maData;
+ }
+
++const OUString* ScDPMember::GetLayoutName() const
++{
++ return mpLayoutName.get();
++}
++
+ String ScDPMember::GetNameStr() const
+ {
+ return maData.aString;
+@@ -2599,6 +2701,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 =
+@@ -2622,6 +2725,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");
+@@ -2641,6 +2750,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 sc/source/filter/excel/read.cxx sc/source/filter/excel/read.cxx
+index 34495e1..af1a672 100644
+--- sc/source/filter/excel/read.cxx
++++ sc/source/filter/excel/read.cxx
+@@ -1171,12 +1171,7 @@ FltError ImportExcel8::Read( void )
+
+ pProgress.reset();
+
+-#if 0
+- // Excel documents look much better without this call; better in the
+- // sense that the row heights are identical to the original heights in
+- // Excel.
+ AdjustRowHeight();
+-#endif
+ PostDocLoad();
+
+ pD->CalcAfterLoad();
+@@ -1192,6 +1187,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 sc/source/filter/excel/xepivot.cxx sc/source/filter/excel/xepivot.cxx
+index 2a4994a..91d7d7f 100644
+--- sc/source/filter/excel/xepivot.cxx
++++ sc/source/filter/excel/xepivot.cxx
+@@ -64,6 +64,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;
+
+ // ============================================================================
+ // Pivot cache
+@@ -942,6 +943,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 String* pVisName = rSaveMem.GetLayoutName();
++ if (pVisName && *pVisName != GetItemName())
++ maItemInfo.SetVisName(*pVisName);
+ }
+
+ void XclExpPTItem::WriteBody( XclExpStream& rStrm )
+@@ -1010,8 +1016,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;
+@@ -1078,7 +1089,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() )
+@@ -1187,10 +1202,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() )
+ {
+@@ -1306,6 +1320,11 @@ 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 rtl::OUString* pLayoutName = rSaveData.GetDataLayoutName();
++ if (pLayoutName)
++ maPTInfo.maDataName = *pLayoutName;
++ else
++ maPTInfo.maDataName = ScGlobal::GetRscString(STR_PIVOT_DATA);
+ }
+
+ void XclExpPivotTable::SetFieldPropertiesFromDim( const ScDPSaveDimension& rSaveDim )
+@@ -1413,17 +1432,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 ----------------------------------------------------------------
+@@ -1503,10 +1526,10 @@ void XclExpPivotTable::WriteSxAutoformat( 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 sc/source/filter/excel/xestring.cxx sc/source/filter/excel/xestring.cxx
+index a367647..6660f33 100644
+--- sc/source/filter/excel/xestring.cxx
++++ sc/source/filter/excel/xestring.cxx
+@@ -380,7 +380,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 );
+@@ -494,6 +495,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 sc/source/filter/excel/xipivot.cxx sc/source/filter/excel/xipivot.cxx
+index 6c7c378..b4d9d84 100644
+--- sc/source/filter/excel/xipivot.cxx
++++ sc/source/filter/excel/xipivot.cxx
+@@ -848,6 +848,11 @@ void XclImpPivotCache::ReadPivotCacheStream( XclImpStream& rStrm )
+ }
+ }
+
++bool XclImpPivotCache::IsRefreshOnLoad() const
++{
++ return static_cast<bool>(maPCInfo.mnFlags & 0x0004);
++}
++
+ // ============================================================================
+ // Pivot table
+ // ============================================================================
+@@ -883,6 +888,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());
+ }
+ }
+
+@@ -1044,7 +1051,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;
+@@ -1076,6 +1083,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;
+ }
+
+@@ -1100,7 +1111,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() ) );
+@@ -1135,7 +1146,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)
+ {
+ }
+
+@@ -1299,7 +1311,7 @@ void XclImpPivotTable::ReadSxex( XclImpStream& rStrm )
+
+ void XclImpPivotTable::ReadSxViewEx9( XclImpStream& rStrm )
+ {
+- rStrm >> maPTAutoFormat;
++ rStrm >> maPTViewEx9Info;
+ }
+
+ // ----------------------------------------------------------------------------
+@@ -1365,12 +1377,32 @@ void XclImpPivotTable::Convert()
+ // create the DataPilot
+ ScDPObject* pDPObj = new ScDPObject( GetDocPtr() );
+ pDPObj->SetName( maPTInfo.maTableName );
++ if (maPTInfo.maDataName.Len() > 0)
++ {
++ aSaveData.SetDataLayoutName(maPTInfo.maDataName);
++ aSaveData.GetDataLayoutDimension()->SetLayoutName(maPTInfo.maDataName);
++ }
++
+ pDPObj->SetSaveData( aSaveData );
+ pDPObj->SetSheetDesc( aDesc );
+ pDPObj->SetOutRange( aOutRange );
+ pDPObj->SetAlive( TRUE );
+- pDPObj->SetHeaderLayout( maPTAutoFormat.mnGridLayout == 0 );
++ pDPObj->SetHeaderLayout( maPTViewEx9Info.mnGridLayout == 0 );
++ if (maPTViewEx9Info.maGrandTotalName.Len() > 0)
++ pDPObj->SetGrandTotalName(maPTViewEx9Info.maGrandTotalName);
++
+ 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();
++ }
+ }
+
+ // ============================================================================
+@@ -1485,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 sc/source/filter/excel/xlpivot.cxx sc/source/filter/excel/xlpivot.cxx
+index c7aa590..31f33e2 100644
+--- sc/source/filter/excel/xlpivot.cxx
++++ sc/source/filter/excel/xlpivot.cxx
+@@ -579,7 +579,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 +641,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 +661,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 +948,82 @@ 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 rtl::OUString* pGrandTotal = rDPObj.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 sc/source/filter/inc/fdumper.hxx sc/source/filter/inc/fdumper.hxx
+index aea8de6..8f57403 100644
+--- sc/source/filter/inc/fdumper.hxx
++++ sc/source/filter/inc/fdumper.hxx
+@@ -31,7 +31,7 @@
+ #ifndef SC_FDUMPER_HXX
+ #define SC_FDUMPER_HXX
+
+-#define SCF_INCL_DUMPER (OSL_DEBUG_LEVEL > 0)
++#define SCF_INCL_DUMPER (OSL_DEBUG_LEVEL > 0) && 0
+
+ #include <map>
+ #include <math.h>
+diff --git sc/source/filter/inc/xepivot.hxx sc/source/filter/inc/xepivot.hxx
+index 62a19b5..89224d4 100644
+--- sc/source/filter/inc/xepivot.hxx
++++ sc/source/filter/inc/xepivot.hxx
+@@ -423,7 +423,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 sc/source/filter/inc/xestring.hxx sc/source/filter/inc/xestring.hxx
+index d4ce93d..fba1f6b 100644
+--- sc/source/filter/inc/xestring.hxx
++++ sc/source/filter/inc/xestring.hxx
+@@ -285,6 +285,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 sc/source/filter/inc/xipivot.hxx sc/source/filter/inc/xipivot.hxx
+index 365ea53..813963c 100644
+--- sc/source/filter/inc/xipivot.hxx
++++ 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 sc/source/filter/inc/xlpivot.hxx sc/source/filter/inc/xlpivot.hxx
+index be40dc9..9f773fa 100644
+--- sc/source/filter/inc/xlpivot.hxx
++++ sc/source/filter/inc/xlpivot.hxx
+@@ -43,6 +43,8 @@
+ #include "xladdress.hxx"
+ #include "dpobject.hxx"
+
++#include <memory>
++
+ class XclImpStream;
+ class XclExpStream;
+
+@@ -669,6 +671,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();
+
+@@ -794,19 +798,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 sc/source/filter/inc/xlstring.hxx sc/source/filter/inc/xlstring.hxx
+index 626b11b..0a078a4 100644
+--- sc/source/filter/inc/xlstring.hxx
++++ 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 sc/source/ui/unoobj/dapiuno.cxx sc/source/ui/unoobj/dapiuno.cxx
+index 61715d8..5874bdd 100644
+--- sc/source/ui/unoobj/dapiuno.cxx
++++ sc/source/ui/unoobj/dapiuno.cxx
+@@ -1605,7 +1605,13 @@ rtl::OUString SAL_CALL ScDataPilotFieldObj::getName() throw(uno::RuntimeExceptio
+ if (pDim->IsDataLayout())
+ return String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM(SC_DATALAYOUT_NAME));
+ else
+- sRet = pDim->GetLayoutName();
++ {
++ const rtl::OUString* pLayoutName = pDim->GetLayoutName();
++ if (pLayoutName)
++ sRet = *pLayoutName;
++ else
++ sRet = pDim->GetName();
++ }
+ }
+ }
+ return sRet;
+@@ -1625,7 +1631,7 @@ void SAL_CALL ScDataPilotFieldObj::setName( const rtl::OUString& aNewName )
+ if (!pDim->IsDataLayout())
+ {
+ String aName(aNewName);
+- pDim->SetLayoutName(&aName);
++ pDim->SetLayoutName(aName);
+ pParent->SetDPObject(pDPObj);
+ }
+ }
Modified: trunk/scratch/sc-xlsutil/src/record.py
==============================================================================
--- trunk/scratch/sc-xlsutil/src/record.py (original)
+++ trunk/scratch/sc-xlsutil/src/record.py Thu Nov 13 20:59:07 2008
@@ -505,6 +505,8 @@
if nameLen > 0:
name, nameLen = globals.getRichText(self.readRemainingBytes(), nameLen)
self.appendLine("grand total name: %s"%name)
+ else:
+ self.appendLine("grand total name: (none)")
return
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]