ooo-build r14499 - in trunk: . patches/test scratch/sc-xlsutil/src



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]