update ooo310-m15
[ooovba.git] / applied_patches / 0192-calc-dp-custom-names-sc.diff
blobac79be29caca201059b9e1297e20789453d63ded
1 diff --git sc/inc/dpobject.hxx sc/inc/dpobject.hxx
2 index 2eff673..854e1da 100644
3 --- sc/inc/dpobject.hxx
4 +++ sc/inc/dpobject.hxx
5 @@ -38,6 +38,8 @@
6 #include "dpoutput.hxx"
7 #include <com/sun/star/sheet/XDimensionsSupplier.hpp>
9 +#include <memory>
11 //------------------------------------------------------------------
13 namespace com { namespace sun { namespace star { namespace sheet {
14 @@ -66,6 +68,7 @@ class ScStrCollection;
15 class TypedScStrCollection;
16 struct PivotField;
17 class ScDPCacheTable;
18 +class ScDPTableData;
20 struct ScDPServiceDesc
22 @@ -101,6 +104,7 @@ private:
23 ScSheetSourceDesc* pSheetDesc; // for sheet data
24 ScImportSourceDesc* pImpDesc; // for database data
25 ScDPServiceDesc* pServDesc; // for external service
26 + ::std::auto_ptr<ScDPTableData> mpTableData;
27 // cached data
28 com::sun::star::uno::Reference<com::sun::star::sheet::XDimensionsSupplier> xSource;
29 ScDPOutput* pOutput;
30 @@ -113,6 +117,7 @@ private:
31 bool bHeaderLayout; // TRUE : grid, FALSE : standard
34 + SC_DLLPRIVATE ScDPTableData* GetTableData();
35 SC_DLLPRIVATE void CreateObjects();
36 SC_DLLPRIVATE void CreateOutput();
38 @@ -167,7 +172,14 @@ public:
39 void SetTag(const String& rNew);
40 const String& GetTag() const { return aTableTag; }
42 - BOOL IsDimNameInUse( const String& rName ) const;
43 + /**
44 + * Data description cell displays the description of a data dimension if
45 + * and only if there is only one data dimension. It's usually located at
46 + * the upper-left corner of the table output.
47 + */
48 + bool IsDataDescriptionCell(const ScAddress& rPos);
50 + bool IsDimNameInUse(const ::rtl::OUString& rName) const;
51 String GetDimName( long nDim, BOOL& rIsDataLayout );
52 BOOL IsDuplicated( long nDim );
53 long GetDimCount();
54 @@ -231,6 +245,8 @@ public:
55 // (button attribute must be present)
56 void RefreshAfterLoad();
58 + void BuildAllDimensionMembers();
60 static BOOL HasRegisteredSources();
61 static com::sun::star::uno::Sequence<rtl::OUString> GetRegisteredSources();
62 static com::sun::star::uno::Reference<com::sun::star::sheet::XDimensionsSupplier>
63 diff --git sc/inc/dpsave.hxx sc/inc/dpsave.hxx
64 index ead2c05..cb381fb 100644
65 --- sc/inc/dpsave.hxx
66 +++ sc/inc/dpsave.hxx
67 @@ -34,9 +34,11 @@
68 #include <tools/string.hxx>
69 #include <tools/list.hxx>
70 #include <com/sun/star/sheet/XDimensionsSupplier.hpp>
71 +#include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
72 #include "scdllapi.h"
73 #include <hash_map>
74 #include <list>
75 +#include <memory>
77 namespace com { namespace sun { namespace star { namespace sheet {
78 struct DataPilotFieldReference;
79 @@ -46,6 +48,7 @@ namespace com { namespace sun { namespace star { namespace sheet {
80 } } } }
82 class ScDPDimensionSaveData;
83 +class ScDPTableData;
85 // --------------------------------------------------------------------
87 @@ -57,6 +60,7 @@ class ScDPSaveMember
89 private:
90 String aName;
91 + ::std::auto_ptr<rtl::OUString> mpLayoutName; // custom name to be displayed in the table.
92 USHORT nVisibleMode;
93 USHORT nShowDetailsMode;
95 @@ -77,18 +81,23 @@ public:
97 void SetName( const String& rNew ); // used if the source member was renamed (groups)
99 + SC_DLLPUBLIC void SetLayoutName( const ::rtl::OUString& rName );
100 + SC_DLLPUBLIC const ::rtl::OUString* GetLayoutName() const;
101 + void RemoveLayoutName();
103 void WriteToSource( const com::sun::star::uno::Reference<
104 com::sun::star::uno::XInterface>& xMember,
105 sal_Int32 nPosition );
109 -class ScDPSaveDimension
110 +class SC_DLLPUBLIC ScDPSaveDimension
112 private:
113 String aName;
114 - String* pLayoutName; // alternative name for layout, not used (yet)
115 String* pSelectedPage;
116 + ::std::auto_ptr<rtl::OUString> mpLayoutName;
117 + ::std::auto_ptr<rtl::OUString> mpSubtotalName;
118 BOOL bIsDataLayout;
119 BOOL bDupFlag;
120 USHORT nOrientation;
121 @@ -127,39 +136,44 @@ public:
123 void SetName( const String& rNew ); // used if the source dim was renamed (groups)
125 - SC_DLLPUBLIC void SetOrientation(USHORT nNew);
126 + void SetOrientation(USHORT nNew);
127 void SetSubTotals(BOOL bSet); // to be removed!
128 - SC_DLLPUBLIC void SetSubTotals(long nCount, const USHORT* pFuncs);
129 + void SetSubTotals(long nCount, const USHORT* pFuncs);
130 long GetSubTotalsCount() const { return nSubTotalCount; }
131 USHORT GetSubTotalFunc(long nIndex) const { return pSubTotalFuncs[nIndex]; }
132 - SC_DLLPUBLIC void SetShowEmpty(BOOL bSet);
133 + void SetShowEmpty(BOOL bSet);
134 BOOL GetShowEmpty() const { return BOOL(nShowEmptyMode); }
135 - SC_DLLPUBLIC void SetFunction(USHORT nNew); // enum GeneralFunction
136 + void SetFunction(USHORT nNew); // enum GeneralFunction
137 USHORT GetFunction() const { return nFunction; }
138 void SetUsedHierarchy(long nNew);
139 long GetUsedHierarchy() const { return nUsedHierarchy; }
140 - SC_DLLPUBLIC void SetLayoutName(const String* pName);
141 - SC_DLLPUBLIC const String& GetLayoutName() const;
142 - SC_DLLPUBLIC BOOL HasLayoutName() const;
144 + void SetLayoutName(const ::rtl::OUString& rName);
145 + const ::rtl::OUString* GetLayoutName() const;
146 + void RemoveLayoutName();
147 + void SetSubtotalName(const ::rtl::OUString& rName);
148 + const ::rtl::OUString* GetSubtotalName() const;
150 + bool IsMemberNameInUse(const ::rtl::OUString& rName) const;
152 const ::com::sun::star::sheet::DataPilotFieldReference* GetReferenceValue() const { return pReferenceValue; }
153 - SC_DLLPUBLIC void SetReferenceValue(const ::com::sun::star::sheet::DataPilotFieldReference* pNew);
154 + void SetReferenceValue(const ::com::sun::star::sheet::DataPilotFieldReference* pNew);
156 const ::com::sun::star::sheet::DataPilotFieldSortInfo* GetSortInfo() const { return pSortInfo; }
157 - SC_DLLPUBLIC void SetSortInfo(const ::com::sun::star::sheet::DataPilotFieldSortInfo* pNew);
158 + void SetSortInfo(const ::com::sun::star::sheet::DataPilotFieldSortInfo* pNew);
159 const ::com::sun::star::sheet::DataPilotFieldAutoShowInfo* GetAutoShowInfo() const { return pAutoShowInfo; }
160 - SC_DLLPUBLIC void SetAutoShowInfo(const ::com::sun::star::sheet::DataPilotFieldAutoShowInfo* pNew);
161 + void SetAutoShowInfo(const ::com::sun::star::sheet::DataPilotFieldAutoShowInfo* pNew);
162 const ::com::sun::star::sheet::DataPilotFieldLayoutInfo* GetLayoutInfo() const { return pLayoutInfo; }
163 - SC_DLLPUBLIC void SetLayoutInfo(const ::com::sun::star::sheet::DataPilotFieldLayoutInfo* pNew);
164 + void SetLayoutInfo(const ::com::sun::star::sheet::DataPilotFieldLayoutInfo* pNew);
166 - SC_DLLPUBLIC void SetCurrentPage( const String* pPage ); // NULL = no selection (all)
167 - SC_DLLPUBLIC BOOL HasCurrentPage() const;
168 - SC_DLLPUBLIC const String& GetCurrentPage() const;
169 + void SetCurrentPage( const String* pPage ); // NULL = no selection (all)
170 + BOOL HasCurrentPage() const;
171 + const String& GetCurrentPage() const;
173 USHORT GetOrientation() const { return nOrientation; }
175 ScDPSaveMember* GetExistingMemberByName(const String& rName);
176 - SC_DLLPUBLIC ScDPSaveMember* GetMemberByName(const String& rName);
177 + ScDPSaveMember* GetMemberByName(const String& rName);
179 void SetMemberPosition( const String& rName, sal_Int32 nNewPos );
181 @@ -180,6 +194,12 @@ private:
182 BOOL bFilterButton; // not passed to DataPilotSource
183 BOOL bDrillDown; // not passed to DataPilotSource
185 + /** if true, all dimensions already have all of their member instances
186 + * created. */
187 + bool mbDimensionMembersBuilt;
189 + ::std::auto_ptr<rtl::OUString> mpGrandTotalName;
191 public:
192 SC_DLLPUBLIC ScDPSaveData();
193 ScDPSaveData(const ScDPSaveData& r);
194 @@ -189,11 +209,15 @@ public:
196 BOOL operator== ( const ScDPSaveData& r ) const;
198 + SC_DLLPUBLIC void SetGrandTotalName(const ::rtl::OUString& rName);
199 + SC_DLLPUBLIC const ::rtl::OUString* GetGrandTotalName() const;
201 const List& GetDimensions() const { return aDimList; }
202 void AddDimension(ScDPSaveDimension* pDim) { aDimList.Insert(pDim, LIST_APPEND); }
204 ScDPSaveDimension* GetDimensionByName(const String& rName);
205 SC_DLLPUBLIC ScDPSaveDimension* GetDataLayoutDimension();
206 + SC_DLLPUBLIC ScDPSaveDimension* GetExistingDataLayoutDimension() const;
208 ScDPSaveDimension* DuplicateDimension(const String& rName);
209 SC_DLLPUBLIC ScDPSaveDimension& DuplicateDimension(const ScDPSaveDimension& rDim);
210 @@ -204,6 +228,7 @@ public:
211 void RemoveDimensionByName(const String& rName);
213 ScDPSaveDimension* GetInnermostDimension(USHORT nOrientation);
214 + ScDPSaveDimension* GetFirstDimension(::com::sun::star::sheet::DataPilotFieldOrientation eOrientation);
215 long GetDataDimensionCount() const;
218 @@ -230,6 +255,7 @@ public:
219 const ScDPDimensionSaveData* GetExistingDimensionData() const { return pDimensionData; }
220 SC_DLLPUBLIC ScDPDimensionSaveData* GetDimensionData(); // create if not there
221 void SetDimensionData( const ScDPDimensionSaveData* pNew ); // copied
222 + void BuildAllDimensionMembers(ScDPTableData* pData);
226 diff --git sc/inc/dptabres.hxx sc/inc/dptabres.hxx
227 index 3fb5ef8..60ad93e 100644
228 --- sc/inc/dptabres.hxx
229 +++ sc/inc/dptabres.hxx
230 @@ -41,6 +41,7 @@
231 #include <hash_map>
232 #include <hash_set>
233 #include <vector>
234 +#include <memory>
236 namespace com { namespace sun { namespace star { namespace sheet {
237 struct DataPilotFieldReference;
238 @@ -262,7 +263,7 @@ public:
240 long GetMeasureCount() const { return nMeasCount; }
241 ScSubTotalFunc GetMeasureFunction(long nMeasure) const;
242 - String GetMeasureString(long nMeasure, BOOL bForce, ScSubTotalFunc eForceFunc) const;
243 + String GetMeasureString(long nMeasure, BOOL bForce, ScSubTotalFunc eForceFunc, bool& rbTotalResult) const;
244 String GetMeasureDimensionName(long nMeasure) const;
245 const ::com::sun::star::sheet::DataPilotFieldReference& GetMeasureRefVal(long nMeasure) const;
246 USHORT GetMeasureRefOrient(long nMeasure) const;
247 @@ -284,6 +285,8 @@ public:
248 const ScDPItemData& rBaseData, long nBaseIndex ) const;
249 BOOL HasCommonElement( const ScDPItemData& rFirstData, long nFirstIndex,
250 const ScDPItemData& rSecondData, long nSecondIndex ) const;
252 + const ScDPSource* GetSource() const;
256 diff --git sc/inc/dptabsrc.hxx sc/inc/dptabsrc.hxx
257 index f7ae03b..9d6e8e4 100644
258 --- sc/inc/dptabsrc.hxx
259 +++ sc/inc/dptabsrc.hxx
260 @@ -33,6 +33,7 @@
262 #include <vector>
263 #include <hash_map>
264 +#include <memory>
265 #include <tools/string.hxx>
266 #include <tools/list.hxx>
267 #include "global.hxx" // enum ScSubTotalFunc
268 @@ -108,7 +109,7 @@ class ScDPSource : public cppu::WeakImplHelper6<
269 com::sun::star::lang::XServiceInfo >
271 private:
272 - ScDPTableData* pData; // data source
273 + ScDPTableData* pData; // data source (ScDPObject manages its life time)
274 ScDPDimensions* pDimensions; // api objects
275 // settings:
276 long nColDims[SC_DAPI_MAXFIELDS];
277 @@ -136,6 +137,8 @@ private:
278 List aRowLevelList;
279 BOOL bResultOverflow;
281 + ::std::auto_ptr<rtl::OUString> mpGrandTotalName;
283 void CreateRes_Impl();
284 void FillMemberResults();
285 void FillLevelList( USHORT nOrientation, List& rList );
286 @@ -162,11 +165,15 @@ public:
287 ScDPTableData* GetData() { return pData; }
288 const ScDPTableData* GetData() const { return pData; }
290 + void SetGrandTotalName(const ::rtl::OUString& rName);
291 + const ::rtl::OUString* GetGrandTotalName() const;
293 USHORT GetOrientation(long nColumn);
294 void SetOrientation(long nColumn, USHORT nNew);
295 long GetPosition(long nColumn);
297 long GetDataDimensionCount();
298 + ScDPDimension* GetDataDimension(long nIndex);
299 String GetDataDimName(long nIndex);
300 BOOL IsDataLayoutDimension(long nDim);
301 USHORT GetDataLayoutOrientation();
302 @@ -333,6 +340,8 @@ private:
303 long nUsedHier;
304 USHORT nFunction; // enum GeneralFunction
305 String aName; // if empty, take from source
306 + ::std::auto_ptr<rtl::OUString> mpLayoutName;
307 + ::std::auto_ptr<rtl::OUString> mpSubtotalName;
308 long nSourceDim; // >=0 if dup'ed
309 ::com::sun::star::sheet::DataPilotFieldReference
310 aReferenceValue; // settings for "show data as" / "displayed value"
311 @@ -350,6 +359,9 @@ public:
312 ScDPDimension* CreateCloneObject();
313 ScDPHierarchies* GetHierarchiesObject();
315 + SC_DLLPUBLIC const ::rtl::OUString* GetLayoutName() const;
316 + const ::rtl::OUString* GetSubtotalName() const;
318 // XNamed
319 virtual ::rtl::OUString SAL_CALL getName() throw(::com::sun::star::uno::RuntimeException);
320 virtual void SAL_CALL setName( const ::rtl::OUString& aName )
321 @@ -736,7 +748,7 @@ private:
322 long nLev;
324 ScDPItemData maData;
325 -// String aCaption; // visible name (changeable by user)
326 + ::std::auto_ptr<rtl::OUString> mpLayoutName;
328 sal_Int32 nPosition; // manual sorting
329 BOOL bVisible;
330 @@ -750,6 +762,7 @@ public:
331 BOOL IsNamedItem( const ScDPItemData& r ) const;
332 String GetNameStr() const;
333 void FillItemData( ScDPItemData& rData ) const;
334 + SC_DLLPUBLIC const ::rtl::OUString* GetLayoutName() const;
336 sal_Int32 Compare( const ScDPMember& rOther ) const; // visible order
338 diff --git sc/inc/unonames.hxx sc/inc/unonames.hxx
339 index abfcf3a..6afb1a3 100644
340 --- sc/inc/unonames.hxx
341 +++ sc/inc/unonames.hxx
342 @@ -563,6 +563,9 @@
343 #define SC_UNO_ROWFIELDCOUNT "RowFieldCount"
344 #define SC_UNO_COLUMNFIELDCOUNT "ColumnFieldCount"
345 #define SC_UNO_DATAFIELDCOUNT "DataFieldCount"
346 +#define SC_UNO_LAYOUTNAME "LayoutName"
347 +#define SC_UNO_FIELD_SUBTOTALNAME "FieldSubtotalName"
348 +#define SC_UNO_GRANDTOTAL_NAME "GrandTotalName"
350 // (preliminary:)
351 #define SC_UNO_REFVALUE "ReferenceValue"
352 diff --git sc/source/core/data/dpobject.cxx sc/source/core/data/dpobject.cxx
353 index d7c9a6c..afa90e9 100644
354 --- sc/source/core/data/dpobject.cxx
355 +++ sc/source/core/data/dpobject.cxx
356 @@ -78,6 +78,7 @@
358 using namespace com::sun::star;
359 using ::std::vector;
360 +using ::std::auto_ptr;
361 using ::com::sun::star::uno::Sequence;
362 using ::com::sun::star::uno::Reference;
363 using ::com::sun::star::uno::UNO_QUERY;
364 @@ -162,6 +163,7 @@ ScDPObject::ScDPObject( ScDocument* pD ) :
365 pSheetDesc( NULL ),
366 pImpDesc( NULL ),
367 pServDesc( NULL ),
368 + mpTableData(NULL),
369 pOutput( NULL ),
370 nAutoFormatIndex( 65535 ),
371 bSettingsChanged( FALSE ),
372 @@ -184,6 +186,7 @@ ScDPObject::ScDPObject(const ScDPObject& r) :
373 pSheetDesc( NULL ),
374 pImpDesc( NULL ),
375 pServDesc( NULL ),
376 + mpTableData(NULL),
377 pOutput( NULL ),
378 bSettingsChanged( FALSE ),
379 bAlive( FALSE ),
380 @@ -342,6 +345,22 @@ void ScDPObject::SetTag(const String& rNew)
381 aTableTag = rNew;
384 +bool ScDPObject::IsDataDescriptionCell(const ScAddress& rPos)
386 + if (!pSaveData)
387 + return false;
389 + long nDataDimCount = pSaveData->GetDataDimensionCount();
390 + if (nDataDimCount != 1)
391 + // There has to be exactly one data dimension for the description to
392 + // appear at top-left corner.
393 + return false;
395 + CreateOutput();
396 + ScRange aTabRange = pOutput->GetOutputRange(sheet::DataPilotOutputRangeType::TABLE);
397 + return (rPos == aTabRange.aStart);
400 uno::Reference<sheet::XDimensionsSupplier> ScDPObject::GetSource()
402 CreateObjects();
403 @@ -384,6 +412,38 @@ void ScDPObject::CreateOutput()
407 +ScDPTableData* ScDPObject::GetTableData()
409 + if (!mpTableData.get())
411 + if ( pImpDesc )
413 + // database data
414 + mpTableData.reset(new ScDatabaseDPData(pDoc, *pImpDesc));
416 + else
418 + // cell data
419 + if (!pSheetDesc)
421 + DBG_ERROR("no source descriptor");
422 + pSheetDesc = new ScSheetSourceDesc; // dummy defaults
424 + mpTableData.reset(new ScSheetDPData(pDoc, *pSheetDesc));
427 + // grouping (for cell or database data)
428 + if ( pSaveData && pSaveData->GetExistingDimensionData() )
430 + auto_ptr<ScDPGroupTableData> pGroupData(new ScDPGroupTableData(mpTableData.release(), pDoc));
431 + pSaveData->GetExistingDimensionData()->WriteToData(*pGroupData);
432 + mpTableData = pGroupData;
436 + return mpTableData.get();
439 void ScDPObject::CreateObjects()
441 // if groups are involved, create a new source with the ScDPGroupTableData
442 @@ -406,33 +466,9 @@ void ScDPObject::CreateObjects()
443 if ( !xSource.is() ) // database or sheet data, or error in CreateSource
445 DBG_ASSERT( !pServDesc, "DPSource could not be created" );
447 - ScDPTableData* pData = NULL;
448 - if ( pImpDesc )
450 - // database data
451 - pData = new ScDatabaseDPData( pDoc, *pImpDesc );
453 - else
455 - // cell data
456 - if (!pSheetDesc)
458 - DBG_ERROR("no source descriptor");
459 - pSheetDesc = new ScSheetSourceDesc; // dummy defaults
461 - pData = new ScSheetDPData( pDoc, *pSheetDesc );
464 - // grouping (for cell or database data)
465 - if ( pSaveData && pSaveData->GetExistingDimensionData() )
467 - ScDPGroupTableData* pGroupData = new ScDPGroupTableData( pData, pDoc );
468 - pSaveData->GetExistingDimensionData()->WriteToData( *pGroupData );
469 - pData = pGroupData;
472 - xSource = new ScDPSource( pData );
473 + ScDPTableData* pData = GetTableData();
474 + ScDPSource* pSource = new ScDPSource( pData );
475 + xSource = pSource;
478 if (pSaveData)
479 @@ -554,6 +590,14 @@ void ScDPObject::RefreshAfterLoad()
480 bInfoValid = TRUE;
483 +void ScDPObject::BuildAllDimensionMembers()
485 + if (!pSaveData)
486 + return;
488 + pSaveData->BuildAllDimensionMembers(GetTableData());
491 void ScDPObject::UpdateReference( UpdateRefMode eUpdateRefMode,
492 const ScRange& rRange, SCsCOL nDx, SCsROW nDy, SCsTAB nDz )
494 @@ -676,23 +720,33 @@ void ScDPObject::GetDrillDownData(const ScAddress& rPos, Sequence< Sequence<Any>
495 rTableData = xDrillDownData->getDrillDownData(filters);
498 -BOOL ScDPObject::IsDimNameInUse( const String& rName ) const
499 +bool ScDPObject::IsDimNameInUse(const OUString& rName) const
501 - if ( xSource.is() )
503 - uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions();
504 - if ( xDimsName.is() )
506 - rtl::OUString aCompare( rName );
507 - uno::Sequence<rtl::OUString> aNames = xDimsName->getElementNames();
508 - long nCount = aNames.getLength();
509 - const rtl::OUString* pArr = aNames.getConstArray();
510 - for (long nPos=0; nPos<nCount; nPos++)
511 - if ( pArr[nPos] == aCompare ) //! ignore case
512 - return TRUE;
515 - return FALSE; // not found
516 + if (!xSource.is())
517 + return false;
519 + Reference<container::XNameAccess> xDims = xSource->getDimensions();
520 + Sequence<OUString> aDimNames = xDims->getElementNames();
521 + sal_Int32 n = aDimNames.getLength();
522 + for (sal_Int32 i = 0; i < n; ++i)
524 + const OUString& rDimName = aDimNames[i];
525 + if (rDimName.equalsIgnoreAsciiCase(rName))
526 + return true;
528 + Reference<beans::XPropertySet> xPropSet(xDims->getByName(rDimName), UNO_QUERY);
529 + if (!xPropSet.is())
530 + continue;
532 + Any any = xPropSet->getPropertyValue(OUString::createFromAscii(SC_UNO_LAYOUTNAME));
533 + OUString aLayoutName;
534 + if (any >>= aLayoutName)
536 + if (aLayoutName.equalsIgnoreAsciiCase(rName))
537 + return true;
540 + return false;
543 String ScDPObject::GetDimName( long nDim, BOOL& rIsDataLayout )
544 diff --git sc/source/core/data/dpoutput.cxx sc/source/core/data/dpoutput.cxx
545 index a411c80..de9c898 100644
546 --- sc/source/core/data/dpoutput.cxx
547 +++ sc/source/core/data/dpoutput.cxx
548 @@ -81,6 +81,7 @@
550 using namespace com::sun::star;
551 using ::std::vector;
552 +using ::com::sun::star::beans::XPropertySet;
553 using ::com::sun::star::uno::Sequence;
554 using ::com::sun::star::uno::UNO_QUERY;
555 using ::com::sun::star::uno::Reference;
556 @@ -98,7 +99,6 @@ using ::rtl::OUString;
557 #define DP_PROP_ORIENTATION "Orientation"
558 #define DP_PROP_POSITION "Position"
559 #define DP_PROP_USEDHIERARCHY "UsedHierarchy"
560 -#define DP_PROP_DATADESCR "DataDescription"
561 #define DP_PROP_ISDATALAYOUT "IsDataLayoutDimension"
562 #define DP_PROP_NUMBERFORMAT "NumberFormat"
563 #define DP_PROP_FILTER "Filter"
564 @@ -119,7 +119,8 @@ struct ScDPOutLevelData
565 long nLevel;
566 long nDimPos;
567 uno::Sequence<sheet::MemberResult> aResult;
568 - String aCaption;
569 + String maName; /// Name is the internal field name.
570 + String aCaption; /// Caption is the name visible in the output table.
572 ScDPOutLevelData() { nDim = nHier = nLevel = nDimPos = -1; }
574 @@ -444,7 +445,15 @@ ScDPOutput::ScDPOutput( ScDocument* pD, const uno::Reference<sheet::XDimensionsS
575 xLevel, uno::UNO_QUERY );
576 if ( xLevNam.is() && xLevRes.is() )
578 - String aCaption = String(xLevNam->getName()); //! Caption...
579 + String aName = xLevNam->getName();
580 + OUString aCaption = aName; // Caption equals the field name by default.
581 + Reference<XPropertySet> xPropSet(xLevel, UNO_QUERY);
582 + if (xPropSet.is())
584 + Any any = xPropSet->getPropertyValue(
585 + OUString::createFromAscii(SC_UNO_LAYOUTNAME));
586 + any >>= aCaption;
588 switch ( eDimOrient )
590 case sheet::DataPilotFieldOrientation_COLUMN:
591 @@ -453,6 +462,7 @@ ScDPOutput::ScDPOutput( ScDocument* pD, const uno::Reference<sheet::XDimensionsS
592 pColFields[nColFieldCount].nLevel = nLev;
593 pColFields[nColFieldCount].nDimPos = nDimPos;
594 pColFields[nColFieldCount].aResult = xLevRes->getResults();
595 + pColFields[nColFieldCount].maName = aName;
596 pColFields[nColFieldCount].aCaption= aCaption;
597 if (!lcl_MemberEmpty(pColFields[nColFieldCount].aResult))
598 ++nColFieldCount;
599 @@ -463,6 +473,7 @@ ScDPOutput::ScDPOutput( ScDocument* pD, const uno::Reference<sheet::XDimensionsS
600 pRowFields[nRowFieldCount].nLevel = nLev;
601 pRowFields[nRowFieldCount].nDimPos = nDimPos;
602 pRowFields[nRowFieldCount].aResult = xLevRes->getResults();
603 + pRowFields[nRowFieldCount].maName = aName;
604 pRowFields[nRowFieldCount].aCaption= aCaption;
605 if (!lcl_MemberEmpty(pRowFields[nRowFieldCount].aResult))
606 ++nRowFieldCount;
607 @@ -473,6 +484,7 @@ ScDPOutput::ScDPOutput( ScDocument* pD, const uno::Reference<sheet::XDimensionsS
608 pPageFields[nPageFieldCount].nLevel = nLev;
609 pPageFields[nPageFieldCount].nDimPos = nDimPos;
610 pPageFields[nPageFieldCount].aResult = lcl_GetSelectedPageAsResult(xDimProp);
611 + pPageFields[nPageFieldCount].maName = aName;
612 pPageFields[nPageFieldCount].aCaption= aCaption;
613 // no check on results for page fields
614 ++nPageFieldCount;
615 @@ -529,7 +541,7 @@ ScDPOutput::ScDPOutput( ScDocument* pD, const uno::Reference<sheet::XDimensionsS
618 uno::Any aAny = xSrcProp->getPropertyValue(
619 - rtl::OUString::createFromAscii(DP_PROP_DATADESCR) );
620 + rtl::OUString::createFromAscii(SC_UNO_DATADESC) );
621 rtl::OUString aUStr;
622 aAny >>= aUStr;
623 aDataDescription = String( aUStr );
624 @@ -606,9 +618,16 @@ void ScDPOutput::HeaderCell( SCCOL nCol, SCROW nRow, SCTAB nTab,
625 const sheet::MemberResult& rData, BOOL bColHeader, long nLevel )
627 long nFlags = rData.Flags;
629 + rtl::OUStringBuffer aCaptionBuf;
630 + if (!(nFlags & sheet::MemberResultFlags::NUMERIC))
631 + // This caption is not a number. Make sure it won't get parsed as one.
632 + aCaptionBuf.append(sal_Unicode('\''));
633 + aCaptionBuf.append(rData.Caption);
635 if ( nFlags & sheet::MemberResultFlags::HASMEMBER )
637 - pDoc->SetString( nCol, nRow, nTab, rData.Caption );
638 + pDoc->SetString( nCol, nRow, nTab, aCaptionBuf.makeStringAndClear() );
640 else
642 @@ -1151,7 +1170,7 @@ bool ScDPOutput::GetDataResultPositionData(vector<sheet::DataPilotFieldFilter>&
643 for (SCCOL nColField = 0; nColField < nColFieldCount && bFilterByCol; ++nColField)
645 sheet::DataPilotFieldFilter filter;
646 - filter.FieldName = pColFields[nColField].aCaption;
647 + filter.FieldName = pColFields[nColField].maName;
649 const uno::Sequence<sheet::MemberResult> rSequence = pColFields[nColField].aResult;
650 const sheet::MemberResult* pArray = rSequence.getConstArray();
651 @@ -1168,10 +1187,15 @@ bool ScDPOutput::GetDataResultPositionData(vector<sheet::DataPilotFieldFilter>&
654 // row fields
655 + bool bDataLayoutExists = (nDataFieldCount > 1);
656 for (SCROW nRowField = 0; nRowField < nRowFieldCount && bFilterByRow; ++nRowField)
658 + if (bDataLayoutExists && nRowField == nRowFieldCount - 1)
659 + // There is no sense including the data layout field for filtering.
660 + continue;
662 sheet::DataPilotFieldFilter filter;
663 - filter.FieldName = pRowFields[nRowField].aCaption;
664 + filter.FieldName = pRowFields[nRowField].maName;
666 const uno::Sequence<sheet::MemberResult> rSequence = pRowFields[nRowField].aResult;
667 const sheet::MemberResult* pArray = rSequence.getConstArray();
668 @@ -1209,8 +1233,7 @@ bool lcl_IsNamedDataField( const ScDPGetPivotDataField& rTarget, const String& r
670 bool lcl_IsNamedCategoryField( const ScDPGetPivotDataField& rFilter, const ScDPOutLevelData& rField )
672 - //! name from source instead of caption?
673 - return ScGlobal::pTransliteration->isEqual( rFilter.maFieldName, rField.aCaption );
674 + return ScGlobal::pTransliteration->isEqual( rFilter.maFieldName, rField.maName );
677 bool lcl_IsCondition( const sheet::MemberResult& rResultEntry, const ScDPGetPivotDataField& rFilter )
678 diff --git sc/source/core/data/dpsave.cxx sc/source/core/data/dpsave.cxx
679 index 130e7a8..f41ea2c 100644
680 --- sc/source/core/data/dpsave.cxx
681 +++ sc/source/core/data/dpsave.cxx
682 @@ -58,7 +58,12 @@
683 #include <com/sun/star/container/XNamed.hpp>
684 #include <com/sun/star/util/XCloneable.hpp>
686 +#include <hash_map>
688 using namespace com::sun::star;
689 +using ::rtl::OUString;
690 +using ::std::hash_map;
691 +using ::std::auto_ptr;
693 // -----------------------------------------------------------------------
695 @@ -113,6 +118,7 @@ void lcl_SkipExtra( SvStream& rStream )
697 ScDPSaveMember::ScDPSaveMember(const String& rName) :
698 aName( rName ),
699 + mpLayoutName(NULL),
700 nVisibleMode( SC_DPSAVEMODE_DONTKNOW ),
701 nShowDetailsMode( SC_DPSAVEMODE_DONTKNOW )
703 @@ -120,9 +126,12 @@ ScDPSaveMember::ScDPSaveMember(const String& rName) :
705 ScDPSaveMember::ScDPSaveMember(const ScDPSaveMember& r) :
706 aName( r.aName ),
707 + mpLayoutName(NULL),
708 nVisibleMode( r.nVisibleMode ),
709 nShowDetailsMode( r.nShowDetailsMode )
711 + if (r.mpLayoutName.get())
712 + mpLayoutName.reset(new OUString(*r.mpLayoutName));
715 ScDPSaveMember::~ScDPSaveMember()
716 @@ -167,6 +176,21 @@ void ScDPSaveMember::SetName( const String& rNew )
717 aName = rNew;
720 +void ScDPSaveMember::SetLayoutName( const OUString& rName )
722 + mpLayoutName.reset(new OUString(rName));
725 +const OUString* ScDPSaveMember::GetLayoutName() const
727 + return mpLayoutName.get();
730 +void ScDPSaveMember::RemoveLayoutName()
732 + mpLayoutName.reset(NULL);
735 void ScDPSaveMember::WriteToSource( const uno::Reference<uno::XInterface>& xMember, sal_Int32 nPosition )
737 // nothing to do?
738 @@ -187,6 +211,18 @@ void ScDPSaveMember::WriteToSource( const uno::Reference<uno::XInterface>& xMemb
739 lcl_SetBoolProperty( xMembProp,
740 rtl::OUString::createFromAscii(DP_PROP_SHOWDETAILS), (BOOL)nShowDetailsMode );
742 + if (mpLayoutName.get())
744 + try
746 + uno::Any any;
747 + any <<= rtl::OUString(*mpLayoutName);
748 + xMembProp->setPropertyValue(rtl::OUString::createFromAscii(SC_UNO_LAYOUTNAME), any);
750 + catch (uno::Exception&)
754 if ( nPosition >= 0 )
757 @@ -205,8 +241,9 @@ void ScDPSaveMember::WriteToSource( const uno::Reference<uno::XInterface>& xMemb
759 ScDPSaveDimension::ScDPSaveDimension(const String& rName, BOOL bDataLayout) :
760 aName( rName ),
761 - pLayoutName( NULL ),
762 pSelectedPage( NULL ),
763 + mpLayoutName(NULL),
764 + mpSubtotalName(NULL),
765 bIsDataLayout( bDataLayout ),
766 bDupFlag( FALSE ),
767 nOrientation( sheet::DataPilotFieldOrientation_HIDDEN ),
768 @@ -225,6 +262,8 @@ ScDPSaveDimension::ScDPSaveDimension(const String& rName, BOOL bDataLayout) :
770 ScDPSaveDimension::ScDPSaveDimension(const ScDPSaveDimension& r) :
771 aName( r.aName ),
772 + mpLayoutName(NULL),
773 + mpSubtotalName(NULL),
774 bIsDataLayout( r.bIsDataLayout ),
775 bDupFlag( r.bDupFlag ),
776 nOrientation( r.nOrientation ),
777 @@ -265,14 +304,14 @@ ScDPSaveDimension::ScDPSaveDimension(const ScDPSaveDimension& r) :
778 pLayoutInfo = new sheet::DataPilotFieldLayoutInfo( *(r.pLayoutInfo) );
779 else
780 pLayoutInfo = NULL;
781 - if (r.pLayoutName)
782 - pLayoutName = new String( *(r.pLayoutName) );
783 - else
784 - pLayoutName = NULL;
785 if (r.pSelectedPage)
786 pSelectedPage = new String( *(r.pSelectedPage) );
787 else
788 pSelectedPage = NULL;
789 + if (r.mpLayoutName.get())
790 + mpLayoutName.reset(new OUString(*r.mpLayoutName));
791 + if (r.mpSubtotalName.get())
792 + mpSubtotalName.reset(new OUString(*r.mpSubtotalName));
795 ScDPSaveDimension::~ScDPSaveDimension()
796 @@ -283,7 +322,6 @@ ScDPSaveDimension::~ScDPSaveDimension()
797 delete pSortInfo;
798 delete pAutoShowInfo;
799 delete pLayoutInfo;
800 - delete pLayoutName;
801 delete pSelectedPage;
802 delete [] pSubTotalFuncs;
804 @@ -395,25 +433,45 @@ void ScDPSaveDimension::SetUsedHierarchy(long nNew)
805 nUsedHierarchy = nNew;
808 -BOOL ScDPSaveDimension::HasLayoutName() const
809 +void ScDPSaveDimension::SetSubtotalName(const OUString& rName)
811 - return ( pLayoutName != NULL );
812 + mpSubtotalName.reset(new OUString(rName));
815 -void ScDPSaveDimension::SetLayoutName(const String* pName)
816 +const OUString* ScDPSaveDimension::GetSubtotalName() const
818 - delete pLayoutName;
819 - if (pName)
820 - pLayoutName = new String( *pName );
821 - else
822 - pLayoutName = NULL;
823 + return mpSubtotalName.get();
826 -const String& ScDPSaveDimension::GetLayoutName() const
827 +bool ScDPSaveDimension::IsMemberNameInUse(const OUString& rName) const
829 - if (pLayoutName)
830 - return *pLayoutName;
831 - return aName;
832 + MemberList::const_iterator itr = maMemberList.begin(), itrEnd = maMemberList.end();
833 + for (; itr != itrEnd; ++itr)
835 + const ScDPSaveMember* pMem = *itr;
836 + if (rName.equalsIgnoreAsciiCase(pMem->GetName()))
837 + return true;
839 + const OUString* pLayoutName = pMem->GetLayoutName();
840 + if (pLayoutName && rName.equalsIgnoreAsciiCase(*pLayoutName))
841 + return true;
843 + return false;
846 +void ScDPSaveDimension::SetLayoutName(const OUString& rName)
848 + mpLayoutName.reset(new OUString(rName));
851 +const OUString* ScDPSaveDimension::GetLayoutName() const
853 + return mpLayoutName.get();
856 +void ScDPSaveDimension::RemoveLayoutName()
858 + mpLayoutName.reset(NULL);
861 void ScDPSaveDimension::SetReferenceValue(const sheet::DataPilotFieldReference* pNew)
862 @@ -549,6 +607,19 @@ void ScDPSaveDimension::WriteToSource( const uno::Reference<uno::XInterface>& xD
864 aAny <<= aFilter;
865 xDimProp->setPropertyValue( rtl::OUString::createFromAscii(DP_PROP_FILTER), aAny );
866 + if (mpLayoutName.get())
868 + aAny <<= *mpLayoutName;
869 + xDimProp->setPropertyValue(rtl::OUString::createFromAscii(SC_UNO_LAYOUTNAME), aAny);
872 + const OUString* pSubTotalName = GetSubtotalName();
873 + if (pSubTotalName)
875 + // Custom subtotal name, with '?' being replaced by the visible field name later.
876 + aAny <<= *pSubTotalName;
877 + xDimProp->setPropertyValue(OUString::createFromAscii(SC_UNO_FIELD_SUBTOTALNAME), aAny);
880 catch ( beans::UnknownPropertyException& )
882 @@ -691,7 +762,9 @@ ScDPSaveData::ScDPSaveData() :
883 nIgnoreEmptyMode( SC_DPSAVEMODE_DONTKNOW ),
884 nRepeatEmptyMode( SC_DPSAVEMODE_DONTKNOW ),
885 bFilterButton( TRUE ),
886 - bDrillDown( TRUE )
887 + bDrillDown( TRUE ),
888 + mbDimensionMembersBuilt(false),
889 + mpGrandTotalName(NULL)
893 @@ -701,7 +774,9 @@ ScDPSaveData::ScDPSaveData(const ScDPSaveData& r) :
894 nIgnoreEmptyMode( r.nIgnoreEmptyMode ),
895 nRepeatEmptyMode( r.nRepeatEmptyMode ),
896 bFilterButton( r.bFilterButton ),
897 - bDrillDown( r.bDrillDown )
898 + bDrillDown( r.bDrillDown ),
899 + mbDimensionMembersBuilt(r.mbDimensionMembersBuilt),
900 + mpGrandTotalName(NULL)
902 if ( r.pDimensionData )
903 pDimensionData = new ScDPDimensionSaveData( *r.pDimensionData );
904 @@ -714,6 +789,9 @@ ScDPSaveData::ScDPSaveData(const ScDPSaveData& r) :
905 ScDPSaveDimension* pNew = new ScDPSaveDimension( *(ScDPSaveDimension*)r.aDimList.GetObject(i) );
906 aDimList.Insert( pNew, LIST_APPEND );
909 + if (r.mpGrandTotalName.get())
910 + mpGrandTotalName.reset(new OUString(*r.mpGrandTotalName));
913 ScDPSaveData& ScDPSaveData::operator= ( const ScDPSaveData& r )
914 @@ -732,6 +810,7 @@ ScDPSaveData& ScDPSaveData::operator= ( const ScDPSaveData& r )
915 nRepeatEmptyMode = r.nRepeatEmptyMode;
916 bFilterButton = r.bFilterButton;
917 bDrillDown = r.bDrillDown;
918 + mbDimensionMembersBuilt = r.mbDimensionMembersBuilt;
920 // remove old dimensions
922 @@ -750,6 +829,9 @@ ScDPSaveData& ScDPSaveData::operator= ( const ScDPSaveData& r )
923 new ScDPSaveDimension( *(ScDPSaveDimension*)r.aDimList.GetObject(i) );
924 aDimList.Insert( pNew, LIST_APPEND );
927 + if (r.mpGrandTotalName.get())
928 + mpGrandTotalName.reset(new OUString(*r.mpGrandTotalName));
930 return *this;
932 @@ -761,7 +843,8 @@ BOOL ScDPSaveData::operator== ( const ScDPSaveData& r ) const
933 nIgnoreEmptyMode != r.nIgnoreEmptyMode ||
934 nRepeatEmptyMode != r.nRepeatEmptyMode ||
935 bFilterButton != r.bFilterButton ||
936 - bDrillDown != r.bDrillDown )
937 + bDrillDown != r.bDrillDown ||
938 + mbDimensionMembersBuilt != r.mbDimensionMembersBuilt)
939 return FALSE;
941 if ( pDimensionData || r.pDimensionData )
942 @@ -777,6 +860,16 @@ BOOL ScDPSaveData::operator== ( const ScDPSaveData& r ) const
943 *(ScDPSaveDimension*)r.aDimList.GetObject(i) ) )
944 return FALSE;
946 + if (mpGrandTotalName.get())
948 + if (!r.mpGrandTotalName.get())
949 + return false;
950 + if (!mpGrandTotalName->equals(*r.mpGrandTotalName))
951 + return false;
953 + else if (r.mpGrandTotalName.get())
954 + return false;
956 return TRUE;
959 @@ -790,6 +883,16 @@ ScDPSaveData::~ScDPSaveData()
960 delete pDimensionData;
963 +void ScDPSaveData::SetGrandTotalName(const OUString& rName)
965 + mpGrandTotalName.reset(new OUString(rName));
968 +const OUString* ScDPSaveData::GetGrandTotalName() const
970 + return mpGrandTotalName.get();
973 ScDPSaveDimension* ScDPSaveData::GetDimensionByName(const String& rName)
975 long nCount = aDimList.Count();
976 @@ -832,6 +935,17 @@ ScDPSaveDimension* ScDPSaveData::GetNewDimensionByName(const String& rName)
978 ScDPSaveDimension* ScDPSaveData::GetDataLayoutDimension()
980 + ScDPSaveDimension* pDim = GetExistingDataLayoutDimension();
981 + if (pDim)
982 + return pDim;
984 + ScDPSaveDimension* pNew = new ScDPSaveDimension( String(), TRUE );
985 + aDimList.Insert( pNew, LIST_APPEND );
986 + return pNew;
989 +ScDPSaveDimension* ScDPSaveData::GetExistingDataLayoutDimension() const
991 long nCount = aDimList.Count();
992 for (long i=0; i<nCount; i++)
994 @@ -839,9 +953,7 @@ ScDPSaveDimension* ScDPSaveData::GetDataLayoutDimension()
995 if ( pDim->IsDataLayout() )
996 return pDim;
998 - ScDPSaveDimension* pNew = new ScDPSaveDimension( String(), TRUE );
999 - aDimList.Insert( pNew, LIST_APPEND );
1000 - return pNew;
1001 + return NULL;
1004 ScDPSaveDimension* ScDPSaveData::DuplicateDimension(const String& rName)
1005 @@ -895,6 +1007,18 @@ ScDPSaveDimension* ScDPSaveData::GetInnermostDimension(USHORT nOrientation)
1006 return pInner; // the last matching one
1009 +ScDPSaveDimension* ScDPSaveData::GetFirstDimension(sheet::DataPilotFieldOrientation eOrientation)
1011 + long nCount = aDimList.Count();
1012 + for (long i = 0; i < nCount; ++i)
1014 + ScDPSaveDimension* pDim = static_cast<ScDPSaveDimension*>(aDimList.GetObject(i));
1015 + if (pDim->GetOrientation() == eOrientation && !pDim->IsDataLayout())
1016 + return pDim;
1018 + return NULL;
1021 long ScDPSaveData::GetDataDimensionCount() const
1023 long nDataCount = 0;
1024 @@ -1002,6 +1126,14 @@ void ScDPSaveData::WriteToSource( const uno::Reference<sheet::XDimensionsSupplie
1025 if ( nRepeatEmptyMode != SC_DPSAVEMODE_DONTKNOW )
1026 lcl_SetBoolProperty( xSourceProp,
1027 rtl::OUString::createFromAscii(DP_PROP_REPEATIFEMPTY), (BOOL)nRepeatEmptyMode );
1029 + const OUString* pGrandTotalName = GetGrandTotalName();
1030 + if (pGrandTotalName)
1032 + uno::Any any;
1033 + any <<= *pGrandTotalName;
1034 + xSourceProp->setPropertyValue(OUString::createFromAscii(SC_UNO_GRANDTOTAL_NAME), any);
1037 catch(uno::Exception&)
1039 @@ -1125,3 +1257,50 @@ void ScDPSaveData::SetDimensionData( const ScDPDimensionSaveData* pNew )
1040 pDimensionData = NULL;
1043 +void ScDPSaveData::BuildAllDimensionMembers(ScDPTableData* pData)
1045 + if (mbDimensionMembersBuilt)
1046 + return;
1048 + // First, build a dimension name-to-index map.
1049 + typedef hash_map<OUString, long, ::rtl::OUStringHash> NameIndexMap;
1050 + NameIndexMap aMap;
1051 + long nColCount = pData->GetColumnCount();
1052 + for (long i = 0; i < nColCount; ++i)
1053 + aMap.insert( NameIndexMap::value_type(pData->getDimensionName(i), i));
1055 + NameIndexMap::const_iterator itrEnd = aMap.end();
1057 + sal_uInt32 n = aDimList.Count();
1058 + for (sal_uInt32 i = 0; i < n; ++i)
1060 + ScDPSaveDimension* pDim = static_cast<ScDPSaveDimension*>(aDimList.GetObject(i));
1061 + const String& rDimName = pDim->GetName();
1062 + if (!rDimName.Len())
1063 + // empty dimension name. It must be data layout.
1064 + continue;
1066 + NameIndexMap::const_iterator itr = aMap.find(rDimName);
1067 + if (itr == itrEnd)
1068 + // dimension name not in the data. This should never happen!
1069 + continue;
1071 + long nDimIndex = itr->second;
1072 + const TypedScStrCollection& rMembers = pData->GetColumnEntries(nDimIndex);
1073 + sal_uInt16 nMemberCount = rMembers.GetCount();
1074 + for (sal_uInt16 j = 0; j < nMemberCount; ++j)
1076 + const String& rMemName = rMembers[j]->GetString();
1077 + if (pDim->GetExistingMemberByName(rMemName))
1078 + // this member instance already exists. nothing to do.
1079 + continue;
1081 + auto_ptr<ScDPSaveMember> pNewMember(new ScDPSaveMember(rMemName));
1082 + pNewMember->SetIsVisible(true);
1083 + pDim->AddMember(pNewMember.release());
1087 + mbDimensionMembersBuilt = true;
1090 diff --git sc/source/core/data/dptabres.cxx sc/source/core/data/dptabres.cxx
1091 index d8f6454..e53ecb9 100644
1092 --- sc/source/core/data/dptabres.cxx
1093 +++ sc/source/core/data/dptabres.cxx
1094 @@ -67,6 +67,7 @@ using ::std::vector;
1095 using ::std::pair;
1096 using ::std::hash_map;
1097 using ::com::sun::star::uno::Sequence;
1098 +using ::rtl::OUString;
1100 // -----------------------------------------------------------------------
1102 @@ -825,11 +826,11 @@ USHORT ScDPResultData::GetMeasureRefOrient(long nMeasure) const
1103 return pMeasRefOrient[nMeasure];
1106 -String ScDPResultData::GetMeasureString(long nMeasure, BOOL bForce, ScSubTotalFunc eForceFunc) const
1107 +String ScDPResultData::GetMeasureString(long nMeasure, BOOL bForce, ScSubTotalFunc eForceFunc, bool& rbTotalResult) const
1109 // with bForce==TRUE, return function instead of "result" for single measure
1110 // with eForceFunc != SUBTOTAL_FUNC_NONE, always use eForceFunc
1112 + rbTotalResult = false;
1113 if ( nMeasure < 0 || ( nMeasCount == 1 && !bForce && eForceFunc == SUBTOTAL_FUNC_NONE ) )
1115 // for user-specified subtotal function with all measures,
1116 @@ -837,12 +838,19 @@ String ScDPResultData::GetMeasureString(long nMeasure, BOOL bForce, ScSubTotalFu
1117 if ( eForceFunc != SUBTOTAL_FUNC_NONE )
1118 return ScGlobal::GetRscString(nFuncStrIds[eForceFunc]);
1120 + rbTotalResult = true;
1121 return ScGlobal::GetRscString(STR_TABLE_ERGEBNIS);
1123 else
1125 DBG_ASSERT( pMeasNames && nMeasure < nMeasCount, "bumm" );
1127 + ScDPDimension* pDataDim = pSource->GetDataDimension(nMeasure);
1128 + if (pDataDim)
1130 + const OUString* pLayoutName = pDataDim->GetLayoutName();
1131 + if (pLayoutName)
1132 + return *pLayoutName;
1134 String aRet;
1135 ScSubTotalFunc eFunc = ( eForceFunc == SUBTOTAL_FUNC_NONE ) ?
1136 GetMeasureFunction(nMeasure) : eForceFunc;
1137 @@ -896,6 +904,11 @@ BOOL ScDPResultData::HasCommonElement( const ScDPItemData& rFirstData, long nFir
1138 return pSource->GetData()->HasCommonElement( rFirstData, nFirstIndex, rSecondData, nSecondIndex );
1141 +const ScDPSource* ScDPResultData::GetSource() const
1143 + return pSource;
1146 // -----------------------------------------------------------------------
1149 @@ -1172,6 +1185,25 @@ void ScDPResultMember::ProcessData( const vector<ScDPItemData>& aChildMembers, c
1153 +/**
1154 + * Parse subtotal string and replace all occurrences of '?' with the
1155 + * caption string.
1156 + */
1157 +static String lcl_parseSubtotalName(const String& rSubStr, const String& rCaption)
1159 + String aNewStr;
1160 + xub_StrLen n = rSubStr.Len();
1161 + for (xub_StrLen i = 0; i < n; ++i)
1163 + sal_Unicode c = rSubStr.GetChar(i);
1164 + if (c == sal_Unicode('?'))
1165 + aNewStr.Append(rCaption);
1166 + else
1167 + aNewStr.Append(c);
1169 + return aNewStr;
1172 void ScDPResultMember::FillMemberResults( uno::Sequence<sheet::MemberResult>* pSequences,
1173 long& rPos, long nMeasure, BOOL bRoot,
1174 const String* pMemberName,
1175 @@ -1204,17 +1236,25 @@ void ScDPResultMember::FillMemberResults( uno::Sequence<sheet::MemberResult>* pS
1178 String aCaption = aName;
1179 + if (pMemberDesc)
1181 + const OUString* pLayoutName = pMemberDesc->GetLayoutName();
1182 + if (pLayoutName)
1184 + aCaption = *pLayoutName;
1185 + bIsNumeric = false; // layout name is always non-numeric.
1189 if ( pMemberCaption ) // use pMemberCaption if != NULL
1190 aCaption = *pMemberCaption;
1191 if (!aCaption.Len())
1192 aCaption = ScGlobal::GetRscString(STR_EMPTYDATA);
1194 - if ( !bIsNumeric )
1196 - // add a "'" character so a string isn't parsed as value in the output cell
1197 - //! have a separate bit in Flags (MemberResultFlags) instead?
1198 - aCaption.Insert( (sal_Unicode) '\'', 0 );
1200 + if (bIsNumeric)
1201 + pArray[rPos].Flags |= sheet::MemberResultFlags::NUMERIC;
1202 + else
1203 + pArray[rPos].Flags &= ~sheet::MemberResultFlags::NUMERIC;
1205 if ( nSize && !bRoot ) // root is overwritten by first dimension
1207 @@ -1277,9 +1317,30 @@ void ScDPResultMember::FillMemberResults( uno::Sequence<sheet::MemberResult>* pS
1208 if (bHasChild)
1209 eForce = lcl_GetForceFunc( pParentLevel, nUserPos );
1211 - String aSubStr = aName; //! caption?
1212 + bool bTotalResult = false;
1213 + String aSubStr = aCaption;
1214 aSubStr += ' ';
1215 - aSubStr += pResultData->GetMeasureString(nMemberMeasure, FALSE, eForce);
1216 + aSubStr += pResultData->GetMeasureString(nMemberMeasure, FALSE, eForce, bTotalResult);
1218 + if (bTotalResult)
1220 + if (pMemberDesc)
1222 + // single data field layout.
1223 + const OUString* pSubtotalName = pParentDim->GetSubtotalName();
1224 + if (pSubtotalName)
1225 + aSubStr = lcl_parseSubtotalName(*pSubtotalName, aCaption);
1226 + pArray[rPos].Flags &= ~sheet::MemberResultFlags::GRANDTOTAL;
1228 + else
1230 + // root member - subtotal (grand total?) for multi-data field layout.
1231 + const rtl::OUString* pGrandTotalName = pResultData->GetSource()->GetGrandTotalName();
1232 + if (pGrandTotalName)
1233 + aSubStr = *pGrandTotalName;
1234 + pArray[rPos].Flags |= sheet::MemberResultFlags::GRANDTOTAL;
1238 pArray[rPos].Name = rtl::OUString(aName);
1239 pArray[rPos].Caption = rtl::OUString(aSubStr);
1240 @@ -2796,8 +2857,9 @@ void ScDPResultDimension::FillMemberResults( uno::Sequence<sheet::MemberResult>*
1241 // in data layout dimension, use first member with different measures/names
1242 if ( bIsDataLayout )
1244 + bool bTotalResult = false;
1245 String aMbrName = pResultData->GetMeasureDimensionName( nSorted );
1246 - String aMbrCapt = pResultData->GetMeasureString( nSorted, FALSE, SUBTOTAL_FUNC_NONE );
1247 + String aMbrCapt = pResultData->GetMeasureString( nSorted, FALSE, SUBTOTAL_FUNC_NONE, bTotalResult );
1248 maMemberArray[0]->FillMemberResults( pSequences, nPos, nSorted, FALSE, &aMbrName, &aMbrCapt );
1250 else if ( pMember->IsVisible() )
1251 diff --git sc/source/core/data/dptabsrc.cxx sc/source/core/data/dptabsrc.cxx
1252 index 499309f..04e75ba 100644
1253 --- sc/source/core/data/dptabsrc.cxx
1254 +++ sc/source/core/data/dptabsrc.cxx
1255 @@ -85,6 +85,7 @@ using ::com::sun::star::uno::Reference;
1256 using ::com::sun::star::uno::Sequence;
1257 using ::com::sun::star::uno::Any;
1258 using ::com::sun::star::sheet::DataPilotFieldAutoShowInfo;
1259 +using ::rtl::OUString;
1261 // -----------------------------------------------------------------------
1263 @@ -141,15 +142,14 @@ ScDPSource::ScDPSource( ScDPTableData* pD ) :
1264 pRowResRoot( NULL ),
1265 pColResults( NULL ),
1266 pRowResults( NULL ),
1267 - bResultOverflow( FALSE )
1268 + bResultOverflow( FALSE ),
1269 + mpGrandTotalName(NULL)
1271 pData->SetEmptyFlags( bIgnoreEmptyRows, bRepeatIfEmpty );
1274 ScDPSource::~ScDPSource()
1276 - delete pData; // ScDPTableData is not ref-counted
1278 if (pDimensions)
1279 pDimensions->release(); // ref-counted
1281 @@ -163,6 +163,16 @@ ScDPSource::~ScDPSource()
1282 delete pResData;
1285 +void ScDPSource::SetGrandTotalName(const ::rtl::OUString& rName)
1287 + mpGrandTotalName.reset(new ::rtl::OUString(rName));
1290 +const ::rtl::OUString* ScDPSource::GetGrandTotalName() const
1292 + return mpGrandTotalName.get();
1295 USHORT ScDPSource::GetOrientation(long nColumn)
1297 long i;
1298 @@ -186,16 +196,21 @@ long ScDPSource::GetDataDimensionCount()
1299 return nDataDimCount;
1302 +ScDPDimension* ScDPSource::GetDataDimension(long nIndex)
1304 + if (nIndex < 0 || nIndex >= nDataDimCount)
1305 + return NULL;
1307 + long nDimIndex = nDataDims[nIndex];
1308 + return GetDimensionsObject()->getByIndex(nDimIndex);
1311 String ScDPSource::GetDataDimName( long nIndex )
1313 String aRet;
1314 - if ( nIndex >= 0 && nIndex < nDataDimCount )
1316 - long nDimIndex = nDataDims[nIndex];
1317 - ScDPDimension* pDim = GetDimensionsObject()->getByIndex(nDimIndex);
1318 - if (pDim)
1319 - aRet = String( pDim->getName() );
1321 + ScDPDimension* pDim = GetDataDimension(nIndex);
1322 + if (pDim)
1323 + aRet = String(pDim->getName());
1324 return aRet;
1327 @@ -484,7 +499,10 @@ String ScDPSource::getDataDescription()
1329 String aRet;
1330 if ( pResData->GetMeasureCount() == 1 )
1331 - aRet = pResData->GetMeasureString( 0, TRUE, SUBTOTAL_FUNC_NONE );
1333 + bool bTotalResult = false;
1334 + aRet = pResData->GetMeasureString( 0, TRUE, SUBTOTAL_FUNC_NONE, bTotalResult );
1337 // empty for more than one measure
1339 @@ -1128,6 +1146,7 @@ uno::Reference<beans::XPropertySetInfo> SAL_CALL ScDPSource::getPropertySetInfo(
1340 throw(uno::RuntimeException)
1342 ScUnoGuard aGuard;
1343 + using beans::PropertyAttribute::READONLY;
1345 static SfxItemPropertyMap aDPSourceMap_Impl[] =
1347 @@ -1136,6 +1155,10 @@ uno::Reference<beans::XPropertySetInfo> SAL_CALL ScDPSource::getPropertySetInfo(
1348 {MAP_CHAR_LEN(SC_UNO_IGNOREEM), 0, &getBooleanCppuType(), 0, 0 }, // for sheet data only
1349 {MAP_CHAR_LEN(SC_UNO_REPEATIF), 0, &getBooleanCppuType(), 0, 0 }, // for sheet data only
1350 {MAP_CHAR_LEN(SC_UNO_ROWGRAND), 0, &getBooleanCppuType(), 0, 0 },
1351 + {MAP_CHAR_LEN(SC_UNO_ROWFIELDCOUNT), 0, &getCppuType(static_cast<sal_Int32*>(0)), READONLY, 0 },
1352 + {MAP_CHAR_LEN(SC_UNO_COLUMNFIELDCOUNT), 0, &getCppuType(static_cast<sal_Int32*>(0)), READONLY, 0 },
1353 + {MAP_CHAR_LEN(SC_UNO_DATAFIELDCOUNT), 0, &getCppuType(static_cast<sal_Int32*>(0)), READONLY, 0 },
1354 + {MAP_CHAR_LEN(SC_UNO_GRANDTOTAL_NAME), 0, &getCppuType(static_cast<OUString*>(0)), 0, 0 },
1355 {0,0,0,0,0,0}
1357 static uno::Reference<beans::XPropertySetInfo> aRef =
1358 @@ -1157,6 +1180,12 @@ void SAL_CALL ScDPSource::setPropertyValue( const rtl::OUString& aPropertyName,
1359 setIgnoreEmptyRows( lcl_GetBoolFromAny( aValue ) );
1360 else if ( aNameStr.EqualsAscii( SC_UNO_REPEATIF ) )
1361 setRepeatIfEmpty( lcl_GetBoolFromAny( aValue ) );
1362 + else if (aNameStr.EqualsAscii(SC_UNO_GRANDTOTAL_NAME))
1364 + OUString aName;
1365 + if (aValue >>= aName)
1366 + mpGrandTotalName.reset(new OUString(aName));
1368 else
1370 DBG_ERROR("unknown property");
1371 @@ -1186,6 +1215,11 @@ uno::Any SAL_CALL ScDPSource::getPropertyValue( const rtl::OUString& aPropertyNa
1372 aRet <<= static_cast<sal_Int32>(nColDimCount);
1373 else if ( aNameStr.EqualsAscii( SC_UNO_DATAFIELDCOUNT ) ) // read-only
1374 aRet <<= static_cast<sal_Int32>(nDataDimCount);
1375 + else if (aNameStr.EqualsAscii(SC_UNO_GRANDTOTAL_NAME))
1377 + if (mpGrandTotalName.get())
1378 + aRet <<= *mpGrandTotalName;
1380 else
1382 DBG_ERROR("unknown property");
1383 @@ -1333,6 +1367,8 @@ ScDPDimension::ScDPDimension( ScDPSource* pSrc, long nD ) :
1384 pHierarchies( NULL ),
1385 nUsedHier( 0 ),
1386 nFunction( SUBTOTAL_FUNC_SUM ), // sum is default
1387 + mpLayoutName(NULL),
1388 + mpSubtotalName(NULL),
1389 nSourceDim( -1 ),
1390 bHasSelectedPage( FALSE ),
1391 pSelectedData( NULL )
1392 @@ -1360,6 +1396,16 @@ ScDPHierarchies* ScDPDimension::GetHierarchiesObject()
1393 return pHierarchies;
1396 +const rtl::OUString* ScDPDimension::GetLayoutName() const
1398 + return mpLayoutName.get();
1401 +const rtl::OUString* ScDPDimension::GetSubtotalName() const
1403 + return mpSubtotalName.get();
1406 uno::Reference<container::XNameAccess> SAL_CALL ScDPDimension::getHierarchies()
1407 throw(uno::RuntimeException)
1409 @@ -1519,6 +1565,8 @@ uno::Reference<beans::XPropertySetInfo> SAL_CALL ScDPDimension::getPropertySetIn
1410 {MAP_CHAR_LEN(SC_UNO_POSITION), 0, &getCppuType((sal_Int32*)0), 0, 0 },
1411 {MAP_CHAR_LEN(SC_UNO_REFVALUE), 0, &getCppuType((sheet::DataPilotFieldReference*)0), 0, 0 },
1412 {MAP_CHAR_LEN(SC_UNO_USEDHIER), 0, &getCppuType((sal_Int32*)0), 0, 0 },
1413 + {MAP_CHAR_LEN(SC_UNO_LAYOUTNAME), 0, &getCppuType(static_cast<rtl::OUString*>(0)), 0, 0 },
1414 + {MAP_CHAR_LEN(SC_UNO_FIELD_SUBTOTALNAME), 0, &getCppuType(static_cast<rtl::OUString*>(0)), 0, 0 },
1415 {0,0,0,0,0,0}
1417 static uno::Reference<beans::XPropertySetInfo> aRef =
1418 @@ -1589,6 +1637,18 @@ void SAL_CALL ScDPDimension::setPropertyValue( const rtl::OUString& aPropertyNam
1420 DELETEZ( pSelectedData ); // invalid after changing aSelectedPage
1422 + else if (aNameStr.EqualsAscii(SC_UNO_LAYOUTNAME))
1424 + OUString aTmpName;
1425 + if (aValue >>= aTmpName)
1426 + mpLayoutName.reset(new OUString(aTmpName));
1428 + else if (aNameStr.EqualsAscii(SC_UNO_FIELD_SUBTOTALNAME))
1430 + OUString aTmpName;
1431 + if (aValue >>= aTmpName)
1432 + mpSubtotalName.reset(new OUString(aTmpName));
1434 else
1436 DBG_ERROR("unknown property");
1437 @@ -1648,6 +1708,10 @@ uno::Any SAL_CALL ScDPDimension::getPropertyValue( const rtl::OUString& aPropert
1438 else
1439 aRet <<= uno::Sequence<sheet::TableFilterField>(0);
1441 + else if (aNameStr.EqualsAscii(SC_UNO_LAYOUTNAME))
1442 + aRet <<= mpLayoutName.get() ? *mpLayoutName : OUString::createFromAscii("");
1443 + else if (aNameStr.EqualsAscii(SC_UNO_FIELD_SUBTOTALNAME))
1444 + aRet <<= mpSubtotalName.get() ? *mpSubtotalName : OUString::createFromAscii("");
1445 else
1447 DBG_ERROR("unknown property");
1448 @@ -2148,7 +2212,11 @@ uno::Sequence<sheet::MemberResult> SAL_CALL ScDPLevel::getResults() throw(uno::R
1449 return aRet;
1452 - return pSource->GetData()->getDimensionName( nSrcDim ); // (original) dimension name
1453 + ScDPDimension* pDim = pSource->GetDimensionsObject()->getByIndex(nSrcDim);
1454 + if (!pDim)
1455 + return rtl::OUString();
1457 + return pDim->getName();
1460 void SAL_CALL ScDPLevel::setName( const ::rtl::OUString& /* rNewName */ ) throw(uno::RuntimeException)
1461 @@ -2251,6 +2319,20 @@ uno::Any SAL_CALL ScDPLevel::getPropertyValue( const rtl::OUString& aPropertyNam
1462 aRet <<= aAutoShowInfo;
1463 else if ( aNameStr.EqualsAscii( SC_UNO_LAYOUT ) )
1464 aRet <<= aLayoutInfo;
1465 + else if (aNameStr.EqualsAscii(SC_UNO_LAYOUTNAME))
1467 + // read only property
1468 + long nSrcDim = pSource->GetSourceDim(nDim);
1469 + ScDPDimension* pDim = pSource->GetDimensionsObject()->getByIndex(nSrcDim);
1470 + if (!pDim)
1471 + return aRet;
1473 + const OUString* pLayoutName = pDim->GetLayoutName();
1474 + if (!pLayoutName)
1475 + return aRet;
1477 + aRet <<= *pLayoutName;
1479 else
1481 DBG_ERROR("unknown property");
1482 @@ -2543,6 +2625,7 @@ ScDPMember::ScDPMember( ScDPSource* pSrc, long nD, long nH, long nL,
1483 nHier( nH ),
1484 nLev( nL ),
1485 maData( rN, fV, bHV ),
1486 + mpLayoutName(NULL),
1487 nPosition( -1 ),
1488 bVisible( TRUE ),
1489 bShowDet( TRUE )
1490 @@ -2603,6 +2686,11 @@ void ScDPMember::FillItemData( ScDPItemData& rData ) const
1491 rData = maData;
1494 +const OUString* ScDPMember::GetLayoutName() const
1496 + return mpLayoutName.get();
1499 String ScDPMember::GetNameStr() const
1501 return maData.aString;
1502 @@ -2662,6 +2750,7 @@ uno::Reference<beans::XPropertySetInfo> SAL_CALL ScDPMember::getPropertySetInfo(
1503 {MAP_CHAR_LEN(SC_UNO_ISVISIBL), 0, &getBooleanCppuType(), 0, 0 },
1504 {MAP_CHAR_LEN(SC_UNO_POSITION), 0, &getCppuType((sal_Int32*)0), 0, 0 },
1505 {MAP_CHAR_LEN(SC_UNO_SHOWDETA), 0, &getBooleanCppuType(), 0, 0 },
1506 + {MAP_CHAR_LEN(SC_UNO_LAYOUTNAME), 0, &getCppuType(static_cast<rtl::OUString*>(0)), 0, 0 },
1507 {0,0,0,0,0,0}
1509 static uno::Reference<beans::XPropertySetInfo> aRef =
1510 @@ -2685,6 +2774,12 @@ void SAL_CALL ScDPMember::setPropertyValue( const rtl::OUString& aPropertyName,
1511 if (aValue >>= nInt)
1512 setPosition( nInt );
1514 + else if (aNameStr.EqualsAscii(SC_UNO_LAYOUTNAME))
1516 + rtl::OUString aName;
1517 + if (aValue >>= aName)
1518 + mpLayoutName.reset(new rtl::OUString(aName));
1520 else
1522 DBG_ERROR("unknown property");
1523 @@ -2704,6 +2799,8 @@ uno::Any SAL_CALL ScDPMember::getPropertyValue( const rtl::OUString& aPropertyNa
1524 lcl_SetBoolInAny( aRet, getShowDetails() );
1525 else if ( aNameStr.EqualsAscii( SC_UNO_POSITION ) )
1526 aRet <<= (sal_Int32) getPosition();
1527 + else if (aNameStr.EqualsAscii(SC_UNO_LAYOUTNAME))
1528 + aRet <<= mpLayoutName.get() ? *mpLayoutName : rtl::OUString();
1529 else
1531 DBG_ERROR("unknown property");
1532 diff --git sc/source/filter/excel/read.cxx sc/source/filter/excel/read.cxx
1533 index 6b486ca..aa2b377 100644
1534 --- sc/source/filter/excel/read.cxx
1535 +++ sc/source/filter/excel/read.cxx
1536 @@ -1199,6 +1199,9 @@ FltError ImportExcel8::Read( void )
1537 eLastErr = SCWARN_IMPORT_ROW_OVERFLOW;
1538 else if( rAddrConv.IsColTruncated() )
1539 eLastErr = SCWARN_IMPORT_COLUMN_OVERFLOW;
1541 + if( GetBiff() == EXC_BIFF8 )
1542 + GetPivotTableManager().MaybeRefreshPivotTables();
1545 return eLastErr;
1546 diff --git sc/source/filter/excel/xepivot.cxx sc/source/filter/excel/xepivot.cxx
1547 index 2e7d2aa..0d43d06 100644
1548 --- sc/source/filter/excel/xepivot.cxx
1549 +++ sc/source/filter/excel/xepivot.cxx
1550 @@ -67,6 +67,7 @@ using ::com::sun::star::sheet::DataPilotFieldSortInfo;
1551 using ::com::sun::star::sheet::DataPilotFieldAutoShowInfo;
1552 using ::com::sun::star::sheet::DataPilotFieldLayoutInfo;
1553 using ::com::sun::star::sheet::DataPilotFieldReference;
1554 +using ::rtl::OUString;
1556 using ::rtl::OString;
1557 using ::rtl::OUString;
1558 @@ -972,6 +973,11 @@ void XclExpPTItem::SetPropertiesFromMember( const ScDPSaveMember& rSaveMem )
1560 ::set_flag( maItemInfo.mnFlags, EXC_SXVI_HIDDEN, !rSaveMem.GetIsVisible() );
1561 ::set_flag( maItemInfo.mnFlags, EXC_SXVI_HIDEDETAIL, !rSaveMem.GetShowDetails() );
1563 + // visible name
1564 + const OUString* pVisName = rSaveMem.GetLayoutName();
1565 + if (pVisName && !pVisName->equals(GetItemName()))
1566 + maItemInfo.SetVisName(*pVisName);
1569 void XclExpPTItem::WriteBody( XclExpStream& rStrm )
1570 @@ -1040,8 +1046,13 @@ void XclExpPTField::SetPropertiesFromDim( const ScDPSaveDimension& rSaveDim )
1571 ::set_flag( maFieldExtInfo.mnFlags, EXC_SXVDEX_SHOWALL, rSaveDim.GetShowEmpty() );
1573 // visible name
1574 - if( rSaveDim.HasLayoutName() && (rSaveDim.GetLayoutName() != GetFieldName()) )
1575 - maFieldInfo.SetVisName( rSaveDim.GetLayoutName() );
1576 + const OUString* pLayoutName = rSaveDim.GetLayoutName();
1577 + if (pLayoutName && !pLayoutName->equals(GetFieldName()))
1578 + maFieldInfo.SetVisName(*pLayoutName);
1580 + const rtl::OUString* pSubtotalName = rSaveDim.GetSubtotalName();
1581 + if (pSubtotalName)
1582 + maFieldExtInfo.mpFieldTotalName.reset(new rtl::OUString(*pSubtotalName));
1584 // subtotals
1585 XclPTSubtotalVec aSubtotals;
1586 @@ -1108,7 +1119,11 @@ void XclExpPTField::SetDataPropertiesFromDim( const ScDPSaveDimension& rSaveDim
1587 rDataInfo.SetApiAggFunc( eFunc );
1589 // visible name
1590 - rDataInfo.SetVisName( lclGetDataFieldCaption( GetFieldName(), eFunc ) );
1591 + const rtl::OUString* pVisName = rSaveDim.GetLayoutName();
1592 + if (pVisName)
1593 + rDataInfo.SetVisName(*pVisName);
1594 + else
1595 + rDataInfo.SetVisName( lclGetDataFieldCaption( GetFieldName(), eFunc ) );
1597 // result field reference
1598 if( const DataPilotFieldReference* pFieldRef = rSaveDim.GetReferenceValue() )
1599 @@ -1217,10 +1232,9 @@ XclExpPivotTable::XclExpPivotTable( const XclExpRoot& rRoot, const ScDPObject& r
1600 // pivot table properties from DP object
1601 mnOutScTab = rOutScRange.aStart.Tab();
1602 maPTInfo.maTableName = rDPObj.GetName();
1603 - maPTInfo.maDataName = ScGlobal::GetRscString( STR_PIVOT_DATA );
1604 maPTInfo.mnCacheIdx = mrPCache.GetCacheIndex();
1606 - maPTAutoFormat.Init( rDPObj );
1607 + maPTViewEx9Info.Init( rDPObj );
1609 if( const ScDPSaveData* pSaveData = rDPObj.GetSaveData() )
1611 @@ -1301,8 +1315,10 @@ void XclExpPivotTable::Save( XclExpStream& rStrm )
1612 WriteSxli( rStrm, maPTInfo.mnDataCols, maPTInfo.mnColFields );
1613 // SXEX
1614 WriteSxex( rStrm );
1615 - // SX_AUTOFORMAT
1616 - WriteSxAutoformat( rStrm );
1617 + // QSISXTAG
1618 + WriteQsiSxTag( rStrm );
1619 + // SXVIEWEX9
1620 + WriteSxViewEx9( rStrm );
1624 @@ -1336,6 +1352,15 @@ void XclExpPivotTable::SetPropertiesFromDP( const ScDPSaveData& rSaveData )
1625 ::set_flag( maPTInfo.mnFlags, EXC_SXVIEW_COLGRAND, rSaveData.GetColumnGrand() );
1626 ::set_flag( maPTExtInfo.mnFlags, EXC_SXEX_DRILLDOWN, rSaveData.GetDrillDown() );
1627 mbFilterBtn = rSaveData.GetFilterButton();
1628 + const ScDPSaveDimension* pDim = rSaveData.GetExistingDataLayoutDimension();
1629 + if (!pDim)
1630 + return;
1632 + const rtl::OUString* pLayoutName = pDim->GetLayoutName();
1633 + if (pLayoutName)
1634 + maPTInfo.maDataName = *pLayoutName;
1635 + else
1636 + maPTInfo.maDataName = ScGlobal::GetRscString(STR_PIVOT_DATA);
1639 void XclExpPivotTable::SetFieldPropertiesFromDim( const ScDPSaveDimension& rSaveDim )
1640 @@ -1443,17 +1468,21 @@ void XclExpPivotTable::Finalize()
1641 rnDataXclRow = rnXclRow1 + maPTInfo.mnColFields + 1;
1642 if( maDataFields.empty() )
1643 ++rnDataXclRow;
1644 - if( 0 == maPTAutoFormat.mnGridLayout )
1646 + bool bExtraHeaderRow = (0 == maPTViewEx9Info.mnGridLayout && maPTInfo.mnColFields == 0);
1647 + if (bExtraHeaderRow)
1648 + // Insert an extra row only when there is no column field.
1649 ++rnDataXclRow;
1651 rnXclCol2 = ::std::max( rnXclCol2, rnDataXclCol );
1652 rnXclRow2 = ::std::max( rnXclRow2, rnDataXclRow );
1653 maPTInfo.mnDataCols = rnXclCol2 - rnDataXclCol + 1;
1654 maPTInfo.mnDataRows = rnXclRow2 - rnDataXclRow + 1;
1656 // first heading
1657 - maPTInfo.mnFirstHeadRow = rnXclRow1 + 1;
1658 - if( 0 == maPTAutoFormat.mnGridLayout )
1659 - maPTInfo.mnFirstHeadRow++;
1660 + maPTInfo.mnFirstHeadRow = rnXclRow1;
1661 + if (bExtraHeaderRow)
1662 + maPTInfo.mnFirstHeadRow += 2;
1665 // records ----------------------------------------------------------------
1666 @@ -1529,14 +1558,68 @@ void XclExpPivotTable::WriteSxex( XclExpStream& rStrm ) const
1667 rStrm.EndRecord();
1670 -void XclExpPivotTable::WriteSxAutoformat( XclExpStream& rStrm ) const
1671 +void XclExpPivotTable::WriteQsiSxTag( XclExpStream& rStrm ) const
1673 + rStrm.StartRecord( 0x0802, 32 );
1675 + sal_uInt16 nRecordType = 0x0802;
1676 + sal_uInt16 nDummyFlags = 0x0000;
1677 + sal_uInt16 nTableType = 1; // 0 = query table : 1 = pivot table
1679 + rStrm << nRecordType << nDummyFlags << nTableType;
1681 + // General flags
1682 + bool bEnableRefresh = true;
1683 + bool bPCacheInvalid = false;
1684 + bool bOlapPTReport = false;
1686 + sal_uInt16 nFlags = 0x0000;
1687 + if (bEnableRefresh) nFlags |= 0x0001;
1688 + if (bPCacheInvalid) nFlags |= 0x0002;
1689 + if (bOlapPTReport) nFlags |= 0x0004;
1690 + rStrm << nFlags;
1692 + // Feature-specific options. The value differs depending on the table
1693 + // type, but we assume the table type is always pivot table.
1694 + sal_uInt32 nOptions = 0x00000000;
1695 + bool bNoStencil = false;
1696 + bool bHideTotal = false;
1697 + bool bEmptyRows = false;
1698 + bool bEmptyCols = false;
1699 + if (bNoStencil) nOptions |= 0x00000001;
1700 + if (bHideTotal) nOptions |= 0x00000002;
1701 + if (bEmptyRows) nOptions |= 0x00000008;
1702 + if (bEmptyCols) nOptions |= 0x00000010;
1703 + rStrm << nOptions;
1705 + enum ExcelVersion
1707 + Excel2000 = 0,
1708 + ExcelXP = 1,
1709 + Excel2003 = 2,
1710 + Excel2007 = 3
1711 + };
1712 + ExcelVersion eXclVer = Excel2000;
1713 + sal_uInt8 nOffsetBytes = 16;
1714 + rStrm << static_cast<sal_uInt8>(eXclVer) // version table last refreshed
1715 + << static_cast<sal_uInt8>(eXclVer) // minimum version to refresh
1716 + << nOffsetBytes
1717 + << static_cast<sal_uInt8>(eXclVer); // first version created
1719 + rStrm << XclExpString(maPTInfo.maTableName);
1720 + rStrm << static_cast<sal_uInt16>(0x0001); // no idea what this is for.
1722 + rStrm.EndRecord();
1725 +void XclExpPivotTable::WriteSxViewEx9( XclExpStream& rStrm ) const
1727 // Until we sync the autoformat ids only export if using grid header layout
1728 // That could only have been set via xls import so far.
1729 - if ( 0 == maPTAutoFormat.mnGridLayout )
1730 + if ( 0 == maPTViewEx9Info.mnGridLayout )
1732 rStrm.StartRecord( EXC_ID_SXVIEWEX9, 17 );
1733 - rStrm << maPTAutoFormat;
1734 + rStrm << maPTViewEx9Info;
1735 rStrm.EndRecord();
1738 diff --git sc/source/filter/excel/xestring.cxx sc/source/filter/excel/xestring.cxx
1739 index e65c6bc..afcd334 100644
1740 --- sc/source/filter/excel/xestring.cxx
1741 +++ sc/source/filter/excel/xestring.cxx
1742 @@ -489,7 +489,8 @@ void XclExpString::WritePhoneticSettings( XclExpStream& rStrm ) const
1744 void XclExpString::Write( XclExpStream& rStrm ) const
1746 - WriteHeader( rStrm );
1747 + if (!mbSkipHeader)
1748 + WriteHeader( rStrm );
1749 WriteBuffer( rStrm );
1750 if( IsWriteFormats() ) // only in BIFF8 included in string
1751 WriteFormats( rStrm );
1752 @@ -662,6 +663,7 @@ void XclExpString::Init( sal_Int32 nCurrLen, XclStrFlags nFlags, sal_uInt16 nMax
1753 mbSmartFlags = bBiff8 && ::get_flag( nFlags, EXC_STR_SMARTFLAGS );
1754 mbSkipFormats = ::get_flag( nFlags, EXC_STR_SEPARATEFORMATS );
1755 mbWrapped = false;
1756 + mbSkipHeader = ::get_flag( nFlags, EXC_STR_NOHEADER );
1757 mnMaxLen = nMaxLen;
1758 SetStrLen( nCurrLen );
1760 diff --git sc/source/filter/excel/xipivot.cxx sc/source/filter/excel/xipivot.cxx
1761 index f0d8c4c..cc449b9 100644
1762 --- sc/source/filter/excel/xipivot.cxx
1763 +++ sc/source/filter/excel/xipivot.cxx
1764 @@ -847,6 +847,11 @@ void XclImpPivotCache::ReadPivotCacheStream( XclImpStream& rStrm )
1768 +bool XclImpPivotCache::IsRefreshOnLoad() const
1770 + return static_cast<bool>(maPCInfo.mnFlags & 0x0004);
1773 // ============================================================================
1774 // Pivot table
1775 // ============================================================================
1776 @@ -882,6 +887,8 @@ void XclImpPTItem::ConvertItem( ScDPSaveDimension& rSaveDim ) const
1777 ScDPSaveMember& rMember = *rSaveDim.GetMemberByName( *pItemName );
1778 rMember.SetIsVisible( !::get_flag( maItemInfo.mnFlags, EXC_SXVI_HIDDEN ) );
1779 rMember.SetShowDetails( !::get_flag( maItemInfo.mnFlags, EXC_SXVI_HIDEDETAIL ) );
1780 + if (maItemInfo.HasVisName())
1781 + rMember.SetLayoutName(*maItemInfo.GetVisName());
1785 @@ -1043,7 +1050,7 @@ ScDPSaveDimension* XclImpPTField::ConvertRCPField( ScDPSaveData& rSaveData ) con
1786 // visible name
1787 if( const String* pVisName = maFieldInfo.GetVisName() )
1788 if( pVisName->Len() > 0 )
1789 - rSaveDim.SetLayoutName( pVisName );
1790 + rSaveDim.SetLayoutName( *pVisName );
1792 // subtotal function(s)
1793 XclPTSubtotalVec aSubtotalVec;
1794 @@ -1075,6 +1082,10 @@ ScDPSaveDimension* XclImpPTField::ConvertRCPField( ScDPSaveData& rSaveData ) con
1795 // grouping info
1796 pCacheField->ConvertGroupField( rSaveData, mrPTable.GetVisFieldNames() );
1798 + // custom subtotal name
1799 + if (maFieldExtInfo.mpFieldTotalName.get())
1800 + rSaveDim.SetSubtotalName(*maFieldExtInfo.mpFieldTotalName);
1802 return &rSaveDim;
1805 @@ -1099,7 +1110,7 @@ void XclImpPTField::ConvertDataFieldInfo( ScDPSaveDimension& rSaveDim, const Xcl
1806 // visible name
1807 if( const String* pVisName = rDataInfo.GetVisName() )
1808 if( pVisName->Len() > 0 )
1809 - rSaveDim.SetLayoutName( pVisName );
1810 + rSaveDim.SetLayoutName( *pVisName );
1812 // aggregation function
1813 rSaveDim.SetFunction( static_cast< USHORT >( rDataInfo.GetApiAggFunc() ) );
1814 @@ -1134,7 +1145,8 @@ void XclImpPTField::ConvertItems( ScDPSaveDimension& rSaveDim ) const
1816 XclImpPivotTable::XclImpPivotTable( const XclImpRoot& rRoot ) :
1817 XclImpRoot( rRoot ),
1818 - maDataOrientField( *this, EXC_SXIVD_DATA )
1819 + maDataOrientField( *this, EXC_SXIVD_DATA ),
1820 + mpDPObj(NULL)
1824 @@ -1298,7 +1310,7 @@ void XclImpPivotTable::ReadSxex( XclImpStream& rStrm )
1826 void XclImpPivotTable::ReadSxViewEx9( XclImpStream& rStrm )
1828 - rStrm >> maPTAutoFormat;
1829 + rStrm >> maPTViewEx9Info;
1832 // ----------------------------------------------------------------------------
1833 @@ -1336,11 +1348,14 @@ void XclImpPivotTable::Convert()
1834 if( const XclImpPTField* pField = GetField( *aIt ) )
1835 pField->ConvertPageField( aSaveData );
1837 +#if 0 // Why do we do this ???
1839 // hidden fields
1840 for( sal_uInt16 nField = 0, nCount = GetFieldCount(); nField < nCount; ++nField )
1841 if( const XclImpPTField* pField = GetField( nField ) )
1842 if( (pField->GetAxes() & EXC_SXVD_AXIS_ROWCOLPAGE) == 0 )
1843 pField->ConvertHiddenField( aSaveData );
1844 +#endif
1846 // data fields
1847 for( aIt = maFiltDataFields.begin(), aEnd = maFiltDataFields.end(); aIt != aEnd; ++aIt )
1848 @@ -1364,12 +1379,30 @@ void XclImpPivotTable::Convert()
1849 // create the DataPilot
1850 ScDPObject* pDPObj = new ScDPObject( GetDocPtr() );
1851 pDPObj->SetName( maPTInfo.maTableName );
1852 + if (maPTInfo.maDataName.Len() > 0)
1853 + aSaveData.GetDataLayoutDimension()->SetLayoutName(maPTInfo.maDataName);
1855 + if (maPTViewEx9Info.maGrandTotalName.Len() > 0)
1856 + aSaveData.SetGrandTotalName(maPTViewEx9Info.maGrandTotalName);
1858 pDPObj->SetSaveData( aSaveData );
1859 pDPObj->SetSheetDesc( aDesc );
1860 pDPObj->SetOutRange( aOutRange );
1861 pDPObj->SetAlive( TRUE );
1862 - pDPObj->SetHeaderLayout( maPTAutoFormat.mnGridLayout == 0 );
1863 + pDPObj->SetHeaderLayout( maPTViewEx9Info.mnGridLayout == 0 );
1865 GetDoc().GetDPCollection()->Insert( pDPObj );
1866 + mpDPObj = pDPObj;
1869 +void XclImpPivotTable::MaybeRefresh()
1871 + if (mpDPObj && mxPCache->IsRefreshOnLoad())
1873 + // 'refresh table on load' flag is set. Refresh the table now. Some
1874 + // Excel files contain partial table output when this flag is set.
1875 + mpDPObj->Output();
1879 // ============================================================================
1880 @@ -1484,85 +1517,10 @@ void XclImpPivotTableManager::ConvertPivotTables()
1881 (*aIt)->Convert();
1884 -// ============================================================================
1886 -// Pivot table autoformat settings ============================================
1888 -/**
1889 -classic : 10 08 00 00 00 00 00 00 20 00 00 00 01 00 00 00 00
1890 -default : 10 08 00 00 00 00 00 00 20 00 00 00 01 00 00 00 00
1891 -report01 : 10 08 02 00 00 00 00 00 20 00 00 00 00 10 00 00 00
1892 -report02 : 10 08 02 00 00 00 00 00 20 00 00 00 01 10 00 00 00
1893 -report03 : 10 08 02 00 00 00 00 00 20 00 00 00 02 10 00 00 00
1894 -report04 : 10 08 02 00 00 00 00 00 20 00 00 00 03 10 00 00 00
1895 -report05 : 10 08 02 00 00 00 00 00 20 00 00 00 04 10 00 00 00
1896 -report06 : 10 08 02 00 00 00 00 00 20 00 00 00 05 10 00 00 00
1897 -report07 : 10 08 02 00 00 00 00 00 20 00 00 00 06 10 00 00 00
1898 -report08 : 10 08 02 00 00 00 00 00 20 00 00 00 07 10 00 00 00
1899 -report09 : 10 08 02 00 00 00 00 00 20 00 00 00 08 10 00 00 00
1900 -report10 : 10 08 02 00 00 00 00 00 20 00 00 00 09 10 00 00 00
1901 -table01 : 10 08 00 00 00 00 00 00 20 00 00 00 0a 10 00 00 00
1902 -table02 : 10 08 00 00 00 00 00 00 20 00 00 00 0b 10 00 00 00
1903 -table03 : 10 08 00 00 00 00 00 00 20 00 00 00 0c 10 00 00 00
1904 -table04 : 10 08 00 00 00 00 00 00 20 00 00 00 0d 10 00 00 00
1905 -table05 : 10 08 00 00 00 00 00 00 20 00 00 00 0e 10 00 00 00
1906 -table06 : 10 08 00 00 00 00 00 00 20 00 00 00 0f 10 00 00 00
1907 -table07 : 10 08 00 00 00 00 00 00 20 00 00 00 10 10 00 00 00
1908 -table08 : 10 08 00 00 00 00 00 00 20 00 00 00 11 10 00 00 00
1909 -table09 : 10 08 00 00 00 00 00 00 20 00 00 00 12 10 00 00 00
1910 -table10 : 10 08 00 00 00 00 00 00 20 00 00 00 13 10 00 00 00
1911 -none : 10 08 00 00 00 00 00 00 20 00 00 00 15 10 00 00 00
1912 -**/
1914 -XclPTAutoFormat::XclPTAutoFormat() :
1915 - mbReport( 0 ),
1916 - mnAutoFormat( 0 ),
1917 - mnGridLayout( 0x10 )
1921 -void XclPTAutoFormat::Init( const ScDPObject& rDPObj )
1923 - if( rDPObj.GetHeaderLayout() )
1925 - mbReport = 0;
1926 - mnAutoFormat = 1;
1927 - mnGridLayout = 0;
1929 - else
1931 - // Report1 for now
1932 - // TODO : sync with autoformat indicies
1933 - mbReport = 2;
1934 - mnAutoFormat = 1;
1935 - mnGridLayout = 0x10;
1939 -XclImpStream& operator>>( XclImpStream& rStrm, XclPTAutoFormat& rInfo )
1941 - rStrm.Ignore( 2 );
1942 - rStrm >> rInfo.mbReport; /// 2 for report* fmts ?
1943 - rStrm.Ignore( 6 );
1944 - sal_uInt8 nDummy;
1945 - return rStrm
1946 - >> rInfo.mnAutoFormat
1947 - >> rInfo.mnGridLayout
1948 - >> nDummy >> nDummy >> nDummy;
1951 -XclExpStream& operator<<( XclExpStream& rStrm, const XclPTAutoFormat& rInfo )
1952 +void XclImpPivotTableManager::MaybeRefreshPivotTables()
1954 - return rStrm
1955 - << EXC_PT_AUTOFMT_HEADER
1956 - << rInfo.mbReport
1957 - << EXC_PT_AUTOFMT_ZERO
1958 - << EXC_PT_AUTOFMT_FLAGS
1959 - << rInfo.mnAutoFormat
1960 - << rInfo.mnGridLayout
1961 - << static_cast<sal_uInt8>(0x00)
1962 - << static_cast<sal_uInt8>(0x00)
1963 - << static_cast<sal_uInt8>(0x00);
1964 + for( XclImpPivotTableVec::iterator aIt = maPTables.begin(), aEnd = maPTables.end(); aIt != aEnd; ++aIt )
1965 + (*aIt)->MaybeRefresh();
1968 // ============================================================================
1969 diff --git sc/source/filter/excel/xlpivot.cxx sc/source/filter/excel/xlpivot.cxx
1970 index e3544b5..c915903 100644
1971 --- sc/source/filter/excel/xlpivot.cxx
1972 +++ sc/source/filter/excel/xlpivot.cxx
1973 @@ -31,6 +31,7 @@
1974 // MARKER(update_precomp.py): autogen include statement, do not remove
1975 #include "precompiled_sc.hxx"
1976 #include "dpgroup.hxx"
1977 +#include "dpsave.hxx"
1978 #include "xestream.hxx"
1979 #include "xistream.hxx"
1980 #include "xestring.hxx"
1981 @@ -581,7 +582,9 @@ XclExpStream& operator<<( XclExpStream& rStrm, const XclPTFieldInfo& rInfo )
1982 XclPTFieldExtInfo::XclPTFieldExtInfo() :
1983 mnFlags( EXC_SXVDEX_DEFAULTFLAGS ),
1984 mnSortField( EXC_SXVDEX_SORT_OWN ),
1985 - mnShowField( EXC_SXVDEX_SHOW_NONE )
1986 + mnShowField( EXC_SXVDEX_SHOW_NONE ),
1987 + mnNumFmt(0),
1988 + mpFieldTotalName(NULL)
1992 @@ -639,10 +642,19 @@ void XclPTFieldExtInfo::SetApiLayoutMode( sal_Int32 nLayoutMode )
1994 XclImpStream& operator>>( XclImpStream& rStrm, XclPTFieldExtInfo& rInfo )
1996 - return rStrm
1997 - >> rInfo.mnFlags
1998 - >> rInfo.mnSortField
1999 - >> rInfo.mnShowField;
2000 + sal_uInt8 nNameLen = 0;
2001 + rStrm >> rInfo.mnFlags
2002 + >> rInfo.mnSortField
2003 + >> rInfo.mnShowField
2004 + >> rInfo.mnNumFmt
2005 + >> nNameLen;
2007 + rStrm.Ignore(10);
2008 + if (nNameLen != 0xFF)
2009 + // Custom field total name is used. Pick it up.
2010 + rInfo.mpFieldTotalName.reset(new rtl::OUString(rStrm.ReadUniString(nNameLen, 0)));
2012 + return rStrm;
2015 XclExpStream& operator<<( XclExpStream& rStrm, const XclPTFieldExtInfo& rInfo )
2016 @@ -650,9 +662,23 @@ XclExpStream& operator<<( XclExpStream& rStrm, const XclPTFieldExtInfo& rInfo )
2017 rStrm << rInfo.mnFlags
2018 << rInfo.mnSortField
2019 << rInfo.mnShowField
2020 - << EXC_SXVDEX_FORMAT_NONE
2021 - << sal_uInt16( 0xFFFF ); // unknown
2022 - rStrm.WriteZeroBytes( 8 ); // unknown
2023 + << EXC_SXVDEX_FORMAT_NONE;
2025 + if (rInfo.mpFieldTotalName.get() && rInfo.mpFieldTotalName->getLength() > 0)
2027 + rtl::OUString aFinalName = *rInfo.mpFieldTotalName;
2028 + if (aFinalName.getLength() >= 254)
2029 + aFinalName = aFinalName.copy(0, 254);
2030 + sal_uInt8 nNameLen = static_cast<sal_uInt8>(aFinalName.getLength());
2031 + rStrm << nNameLen;
2032 + rStrm.WriteZeroBytes(10);
2033 + rStrm << XclExpString(aFinalName, EXC_STR_NOHEADER);
2035 + else
2037 + rStrm << sal_uInt16(0xFFFF);
2038 + rStrm.WriteZeroBytes(8);
2040 return rStrm;
2043 @@ -923,3 +949,86 @@ XclExpStream& operator<<( XclExpStream& rStrm, const XclPTExtInfo& rInfo )
2045 // ============================================================================
2047 +// Pivot table autoformat settings ============================================
2049 +/**
2050 +classic : 10 08 00 00 00 00 00 00 20 00 00 00 01 00 00 00 00
2051 +default : 10 08 00 00 00 00 00 00 20 00 00 00 01 00 00 00 00
2052 +report01 : 10 08 02 00 00 00 00 00 20 00 00 00 00 10 00 00 00
2053 +report02 : 10 08 02 00 00 00 00 00 20 00 00 00 01 10 00 00 00
2054 +report03 : 10 08 02 00 00 00 00 00 20 00 00 00 02 10 00 00 00
2055 +report04 : 10 08 02 00 00 00 00 00 20 00 00 00 03 10 00 00 00
2056 +report05 : 10 08 02 00 00 00 00 00 20 00 00 00 04 10 00 00 00
2057 +report06 : 10 08 02 00 00 00 00 00 20 00 00 00 05 10 00 00 00
2058 +report07 : 10 08 02 00 00 00 00 00 20 00 00 00 06 10 00 00 00
2059 +report08 : 10 08 02 00 00 00 00 00 20 00 00 00 07 10 00 00 00
2060 +report09 : 10 08 02 00 00 00 00 00 20 00 00 00 08 10 00 00 00
2061 +report10 : 10 08 02 00 00 00 00 00 20 00 00 00 09 10 00 00 00
2062 +table01 : 10 08 00 00 00 00 00 00 20 00 00 00 0a 10 00 00 00
2063 +table02 : 10 08 00 00 00 00 00 00 20 00 00 00 0b 10 00 00 00
2064 +table03 : 10 08 00 00 00 00 00 00 20 00 00 00 0c 10 00 00 00
2065 +table04 : 10 08 00 00 00 00 00 00 20 00 00 00 0d 10 00 00 00
2066 +table05 : 10 08 00 00 00 00 00 00 20 00 00 00 0e 10 00 00 00
2067 +table06 : 10 08 00 00 00 00 00 00 20 00 00 00 0f 10 00 00 00
2068 +table07 : 10 08 00 00 00 00 00 00 20 00 00 00 10 10 00 00 00
2069 +table08 : 10 08 00 00 00 00 00 00 20 00 00 00 11 10 00 00 00
2070 +table09 : 10 08 00 00 00 00 00 00 20 00 00 00 12 10 00 00 00
2071 +table10 : 10 08 00 00 00 00 00 00 20 00 00 00 13 10 00 00 00
2072 +none : 10 08 00 00 00 00 00 00 20 00 00 00 15 10 00 00 00
2073 +**/
2075 +XclPTViewEx9Info::XclPTViewEx9Info() :
2076 + mbReport( 0 ),
2077 + mnAutoFormat( 0 ),
2078 + mnGridLayout( 0x10 )
2082 +void XclPTViewEx9Info::Init( const ScDPObject& rDPObj )
2084 + if( rDPObj.GetHeaderLayout() )
2086 + mbReport = 0;
2087 + mnAutoFormat = 1;
2088 + mnGridLayout = 0;
2090 + else
2092 + // Report1 for now
2093 + // TODO : sync with autoformat indicies
2094 + mbReport = 2;
2095 + mnAutoFormat = 1;
2096 + mnGridLayout = 0x10;
2099 + const ScDPSaveData* pData = rDPObj.GetSaveData();
2100 + if (pData)
2102 + const rtl::OUString* pGrandTotal = pData->GetGrandTotalName();
2103 + if (pGrandTotal)
2104 + maGrandTotalName = *pGrandTotal;
2108 +XclImpStream& operator>>( XclImpStream& rStrm, XclPTViewEx9Info& rInfo )
2110 + rStrm.Ignore( 2 );
2111 + rStrm >> rInfo.mbReport; /// 2 for report* fmts ?
2112 + rStrm.Ignore( 6 );
2113 + rStrm >> rInfo.mnAutoFormat >> rInfo.mnGridLayout;
2114 + rInfo.maGrandTotalName = rStrm.ReadUniString();
2115 + return rStrm;
2118 +XclExpStream& operator<<( XclExpStream& rStrm, const XclPTViewEx9Info& rInfo )
2120 + return rStrm
2121 + << EXC_PT_AUTOFMT_HEADER
2122 + << rInfo.mbReport
2123 + << EXC_PT_AUTOFMT_ZERO
2124 + << EXC_PT_AUTOFMT_FLAGS
2125 + << rInfo.mnAutoFormat
2126 + << rInfo.mnGridLayout
2127 + << XclExpString(rInfo.maGrandTotalName, EXC_STR_DEFAULT, EXC_PT_MAXSTRLEN);
2130 diff --git sc/source/filter/inc/xepivot.hxx sc/source/filter/inc/xepivot.hxx
2131 index 2de57fa..2078003 100644
2132 --- sc/source/filter/inc/xepivot.hxx
2133 +++ sc/source/filter/inc/xepivot.hxx
2134 @@ -412,8 +412,10 @@ private:
2135 void WriteSxli( XclExpStream& rStrm, sal_uInt16 nLineCount, sal_uInt16 nIndexCount ) const;
2136 /** Writes the SXEX records containing additional pivot table info. */
2137 void WriteSxex( XclExpStream& rStrm ) const;
2139 + void WriteQsiSxTag( XclExpStream& rStrm ) const;
2140 /** Writes the SX_AUTOFORMAT records with the autoformat id and header layout */
2141 - void WriteSxAutoformat( XclExpStream& rStrm ) const;
2142 + void WriteSxViewEx9( XclExpStream& rStrm ) const;
2144 // ------------------------------------------------------------------------
2145 private:
2146 @@ -424,7 +426,7 @@ private:
2147 const XclExpPivotCache& mrPCache; /// The pivot cache this pivot table bases on.
2148 XclPTInfo maPTInfo; /// Info about the pivot table (SXVIEW record).
2149 XclPTExtInfo maPTExtInfo; /// Extended info about the pivot table (SXEX record).
2150 - XclPTAutoFormat maPTAutoFormat; /// The selected autoformat (SXVIEWEX9)
2151 + XclPTViewEx9Info maPTViewEx9Info; /// The selected autoformat (SXVIEWEX9)
2152 XclExpPTFieldList maFieldList; /// All fields in pivot cache order.
2153 ScfUInt16Vec maRowFields; /// Row field indexes.
2154 ScfUInt16Vec maColFields; /// Column field indexes.
2155 diff --git sc/source/filter/inc/xestring.hxx sc/source/filter/inc/xestring.hxx
2156 index a7443cb..8851736 100644
2157 --- sc/source/filter/inc/xestring.hxx
2158 +++ sc/source/filter/inc/xestring.hxx
2159 @@ -341,6 +341,7 @@ private:
2160 bool mbSmartFlags; /// true = omit flags on empty string; false = always write flags.
2161 bool mbSkipFormats; /// true = skip formats on export; false = write complete formatted string.
2162 bool mbWrapped; /// true = text contains several paragraphs.
2163 + bool mbSkipHeader; /// ture = skip length and flags when writing string bytes.
2166 inline bool operator==( const XclExpString& rLeft, const XclExpString& rRight )
2167 diff --git sc/source/filter/inc/xipivot.hxx sc/source/filter/inc/xipivot.hxx
2168 index 365ea53..813963c 100644
2169 --- sc/source/filter/inc/xipivot.hxx
2170 +++ sc/source/filter/inc/xipivot.hxx
2171 @@ -186,6 +186,8 @@ public:
2172 /** Reads the entire pivot cache stream. Uses decrypter from passed stream. */
2173 void ReadPivotCacheStream( XclImpStream& rStrm );
2175 + bool IsRefreshOnLoad() const;
2177 private:
2178 typedef ::std::vector< XclImpPCFieldRef > XclImpPCFieldVec;
2180 @@ -359,6 +361,8 @@ public:
2181 /** Inserts the pivot table into the Calc document. */
2182 void Convert();
2184 + void MaybeRefresh();
2186 // ------------------------------------------------------------------------
2187 private:
2188 typedef ::std::vector< XclImpPTFieldRef > XclImpPTFieldVec;
2189 @@ -367,7 +371,7 @@ private:
2191 XclPTInfo maPTInfo; /// General info about the pivot table (SXVIEW record).
2192 XclPTExtInfo maPTExtInfo; /// Extended info about the pivot table (SXEX record).
2193 - XclPTAutoFormat maPTAutoFormat; /// The selected autoformat (SX_AUTOFORMAT)
2194 + XclPTViewEx9Info maPTViewEx9Info; /// (SXVIEWEX9 record)
2195 XclImpPTFieldVec maFields; /// Vector containing all fields.
2196 XclImpPTFieldRef mxCurrField; /// Current field for importing additional info.
2197 ScfStringVec maVisFieldNames; /// Vector containing all visible field names.
2198 @@ -378,6 +382,7 @@ private:
2199 ScfUInt16Vec maFiltDataFields; /// Filtered data field indexes.
2200 XclImpPTField maDataOrientField; /// Special data field orientation field.
2201 ScRange maOutScRange; /// Output range in the Calc document.
2202 + ScDPObject* mpDPObj;
2205 typedef ScfRef< XclImpPivotTable > XclImpPivotTableRef;
2206 @@ -437,6 +442,8 @@ public:
2207 /** Inserts all pivot tables into the Calc document. */
2208 void ConvertPivotTables();
2210 + void MaybeRefreshPivotTables();
2212 private:
2213 typedef ::std::vector< XclImpPivotCacheRef > XclImpPivotCacheVec;
2214 typedef ::std::vector< XclImpPivotTableRef > XclImpPivotTableVec;
2215 diff --git sc/source/filter/inc/xlpivot.hxx sc/source/filter/inc/xlpivot.hxx
2216 index 5b88882..8b5bd4e 100644
2217 --- sc/source/filter/inc/xlpivot.hxx
2218 +++ sc/source/filter/inc/xlpivot.hxx
2219 @@ -43,6 +43,8 @@
2220 #include "xladdress.hxx"
2221 #include "dpobject.hxx"
2223 +#include <memory>
2225 class XclImpStream;
2226 class XclExpStream;
2228 @@ -671,6 +673,8 @@ struct XclPTFieldExtInfo
2229 sal_uInt32 mnFlags; /// Several flags and number of items for AutoShow.
2230 sal_uInt16 mnSortField; /// Index to data field sorting bases on.
2231 sal_uInt16 mnShowField; /// Index to data field AutoShow bases on.
2232 + sal_uInt16 mnNumFmt;
2233 + ::std::auto_ptr<rtl::OUString> mpFieldTotalName;
2235 explicit XclPTFieldExtInfo();
2237 @@ -796,19 +800,20 @@ XclExpStream& operator<<( XclExpStream& rStrm, const XclPTExtInfo& rInfo );
2239 // Pivot table autoformat settings ==============================================
2241 -/** Pivot table autoformat settings (SX_AUTOFORMAT record). */
2242 -struct XclPTAutoFormat
2243 +/** Pivot table autoformat settings (SXVIEWEX9 record). */
2244 +struct XclPTViewEx9Info
2246 sal_uInt32 mbReport; /// 2 for report* fmts ?
2247 sal_uInt8 mnAutoFormat; /// AutoFormat ID
2248 sal_uInt8 mnGridLayout; /// 0 == gridlayout, 0x10 == modern
2249 + String maGrandTotalName;
2251 - explicit XclPTAutoFormat();
2252 + explicit XclPTViewEx9Info();
2253 void Init( const ScDPObject& rDPObj );
2256 -XclImpStream& operator>>( XclImpStream& rStrm, XclPTAutoFormat& rInfo );
2257 -XclExpStream& operator<<( XclExpStream& rStrm, const XclPTAutoFormat& rInfo );
2258 +XclImpStream& operator>>( XclImpStream& rStrm, XclPTViewEx9Info& rInfo );
2259 +XclExpStream& operator<<( XclExpStream& rStrm, const XclPTViewEx9Info& rInfo );
2261 // ============================================================================
2262 #endif
2263 diff --git sc/source/filter/inc/xlstring.hxx sc/source/filter/inc/xlstring.hxx
2264 index 0b30049..89f8275 100644
2265 --- sc/source/filter/inc/xlstring.hxx
2266 +++ sc/source/filter/inc/xlstring.hxx
2267 @@ -43,6 +43,7 @@ const XclStrFlags EXC_STR_FORCEUNICODE = 0x0001; /// Always use UCS-2 cha
2268 const XclStrFlags EXC_STR_8BITLENGTH = 0x0002; /// 8-bit string length field (default: 16-bit).
2269 const XclStrFlags EXC_STR_SMARTFLAGS = 0x0004; /// Omit flags on empty string (default: read/write always). BIFF8 only.
2270 const XclStrFlags EXC_STR_SEPARATEFORMATS = 0x0008; /// Import: Keep old formats when reading unformatted string (default: clear formats); Export: Write unformatted string.
2271 +const XclStrFlags EXC_STR_NOHEADER = 0x0010; /// Export: Don't write the length and flag fields.
2273 // ----------------------------------------------------------------------------
2275 diff --git sc/source/ui/dbgui/pvfundlg.cxx sc/source/ui/dbgui/pvfundlg.cxx
2276 index 6dc4551..880a14b 100644
2277 --- sc/source/ui/dbgui/pvfundlg.cxx
2278 +++ sc/source/ui/dbgui/pvfundlg.cxx
2279 @@ -705,7 +705,9 @@ ScDPShowDetailDlg::ScDPShowDetailDlg( Window* pParent, ScDPObject& rDPObj, USHOR
2280 maLbDims ( this, ScResId( LB_DIMS ) ),
2281 maBtnOk ( this, ScResId( BTN_OK ) ),
2282 maBtnCancel ( this, ScResId( BTN_CANCEL ) ),
2283 - maBtnHelp ( this, ScResId( BTN_HELP ) )
2284 + maBtnHelp ( this, ScResId( BTN_HELP ) ),
2286 + mrDPObj(rDPObj)
2288 FreeResource();
2290 @@ -719,7 +721,13 @@ ScDPShowDetailDlg::ScDPShowDetailDlg( Window* pParent, ScDPObject& rDPObj, USHOR
2292 const ScDPSaveDimension* pDimension = pSaveData ? pSaveData->GetExistingDimensionByName(aName) : 0;
2293 if ( !pDimension || (pDimension->GetOrientation() != nOrient) )
2295 + const OUString* pLayoutName = pDimension->GetLayoutName();
2296 + if (pLayoutName)
2297 + aName = *pLayoutName;
2298 maLbDims.InsertEntry( aName );
2299 + maNameIndexMap.insert(DimNameIndexMap::value_type(aName, nDim));
2303 if( maLbDims.GetEntryCount() )
2304 @@ -735,7 +743,17 @@ short ScDPShowDetailDlg::Execute()
2306 String ScDPShowDetailDlg::GetDimensionName() const
2308 - return maLbDims.GetSelectEntry();
2309 + // Look up the internal dimension name which may be different from the
2310 + // displayed field name.
2311 + String aSelectedName = maLbDims.GetSelectEntry();
2312 + DimNameIndexMap::const_iterator itr = maNameIndexMap.find(aSelectedName);
2313 + if (itr == maNameIndexMap.end())
2314 + // This should never happen!
2315 + return aSelectedName;
2317 + long nDim = itr->second;
2318 + BOOL bIsDataLayout = false;
2319 + return mrDPObj.GetDimName(nDim, bIsDataLayout);
2322 IMPL_LINK( ScDPShowDetailDlg, DblClickHdl, ListBox*, pLBox )
2323 diff --git sc/source/ui/dbgui/pvlaydlg.cxx sc/source/ui/dbgui/pvlaydlg.cxx
2324 index bedf6c3..4dee615 100644
2325 --- sc/source/ui/dbgui/pvlaydlg.cxx
2326 +++ sc/source/ui/dbgui/pvlaydlg.cxx
2327 @@ -63,6 +63,7 @@
2328 #include "sc.hrc" //CHINA001
2329 #include "scabstdlg.hxx" //CHINA001
2330 using namespace com::sun::star;
2331 +using ::rtl::OUString;
2333 //----------------------------------------------------------------------------
2335 @@ -1506,6 +1507,8 @@ IMPL_LINK( ScDPLayoutDlg, OkHdl, OKButton *, EMPTYARG )
2336 nPageCount, nColCount, nRowCount, nDataCount );
2337 if ( bFit )
2339 + ScDPSaveData* pOldSaveData = xDlgDPObject->GetSaveData();
2341 ScRange aOutRange( aAdrDest ); // bToNewTable is passed separately
2343 ScDPSaveData aSaveData;
2344 @@ -1537,6 +1540,22 @@ IMPL_LINK( ScDPLayoutDlg, OkHdl, OKButton *, EMPTYARG )
2345 pDim->SetSortInfo( &aIt->maSortInfo );
2346 pDim->SetLayoutInfo( &aIt->maLayoutInfo );
2347 pDim->SetAutoShowInfo( &aIt->maShowInfo );
2348 + ScDPSaveDimension* pOldDim = NULL;
2349 + if (pOldSaveData)
2351 + // Transfer the existing layout names to new dimension instance.
2352 + pOldDim = pOldSaveData->GetExistingDimensionByName(aIt->maName);
2353 + if (pOldDim)
2355 + const OUString* pLayoutName = pOldDim->GetLayoutName();
2356 + if (pLayoutName)
2357 + pDim->SetLayoutName(*pLayoutName);
2359 + const OUString* pSubtotalName = pOldDim->GetSubtotalName();
2360 + if (pSubtotalName)
2361 + pDim->SetSubtotalName(*pSubtotalName);
2365 bool bManualSort = ( aIt->maSortInfo.Mode == sheet::DataPilotFieldSortMode::MANUAL );
2367 @@ -1557,11 +1576,33 @@ IMPL_LINK( ScDPLayoutDlg, OkHdl, OKButton *, EMPTYARG )
2368 ScDPSaveMember* pMember = pDim->GetMemberByName( *pItem );
2369 pMember->SetIsVisible( bIsVisible );
2370 pMember->SetShowDetails( bShowDetails );
2371 + if (pOldDim)
2373 + // Transfer the existing layout name.
2374 + ScDPSaveMember* pOldMember = pOldDim->GetMemberByName(*pItem);
2375 + if (pOldMember)
2377 + const OUString* pLayoutName = pOldMember->GetLayoutName();
2378 + if (pLayoutName)
2379 + pMember->SetLayoutName(*pLayoutName);
2387 + ScDPSaveDimension* pDim = aSaveData.GetDataLayoutDimension();
2388 + if (pDim && pOldSaveData)
2390 + ScDPSaveDimension* pOldDim = pOldSaveData->GetDataLayoutDimension();
2391 + if (pOldDim)
2393 + const OUString* pLayoutName = pOldDim->GetLayoutName();
2394 + if (pLayoutName)
2395 + pDim->SetLayoutName(*pLayoutName);
2399 USHORT nWhichPivot = SC_MOD()->GetPool().GetWhich( SID_PIVOT_TABLE );
2400 ScPivotItem aOutItem( nWhichPivot, &aSaveData, &aOutRange, bToNewTable );
2401 diff --git sc/source/ui/inc/pvfundlg.hxx sc/source/ui/inc/pvfundlg.hxx
2402 index 804f162..1707cd6 100644
2403 --- sc/source/ui/inc/pvfundlg.hxx
2404 +++ sc/source/ui/inc/pvfundlg.hxx
2405 @@ -55,6 +55,8 @@
2406 #include <sfx2/itemconnect.hxx>
2407 #include "pivot.hxx"
2409 +#include <hash_map>
2411 // ============================================================================
2413 typedef sfx::ListBoxWrapper< sal_Int32 > ScDPListBoxWrapper;
2414 @@ -217,6 +219,11 @@ public:
2416 virtual short Execute();
2418 + /**
2419 + * @return String internal name of the selected field. Note that this may
2420 + * be different from the name displayed in the dialog if the field
2421 + * has a layout name.
2422 + */
2423 String GetDimensionName() const;
2425 private:
2426 @@ -228,6 +235,10 @@ private:
2427 OKButton maBtnOk;
2428 CancelButton maBtnCancel;
2429 HelpButton maBtnHelp;
2431 + typedef ::std::hash_map<String, long, ScStringHashCode> DimNameIndexMap;
2432 + DimNameIndexMap maNameIndexMap;
2433 + ScDPObject& mrDPObj;
2436 // ============================================================================
2437 diff --git sc/source/ui/unoobj/dapiuno.cxx sc/source/ui/unoobj/dapiuno.cxx
2438 index 8732865..7a72040 100644
2439 --- sc/source/ui/unoobj/dapiuno.cxx
2440 +++ sc/source/ui/unoobj/dapiuno.cxx
2441 @@ -1605,7 +1605,13 @@ rtl::OUString SAL_CALL ScDataPilotFieldObj::getName() throw(uno::RuntimeExceptio
2442 if (pDim->IsDataLayout())
2443 return String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM(SC_DATALAYOUT_NAME));
2444 else
2445 - sRet = pDim->GetLayoutName();
2447 + const rtl::OUString* pLayoutName = pDim->GetLayoutName();
2448 + if (pLayoutName)
2449 + sRet = *pLayoutName;
2450 + else
2451 + sRet = pDim->GetName();
2455 return sRet;
2456 @@ -1625,7 +1631,7 @@ void SAL_CALL ScDataPilotFieldObj::setName( const rtl::OUString& aNewName )
2457 if (!pDim->IsDataLayout())
2459 String aName(aNewName);
2460 - pDim->SetLayoutName(&aName);
2461 + pDim->SetLayoutName(aName);
2462 pParent->SetDPObject(pDPObj);
2465 diff --git sc/source/ui/view/dbfunc3.cxx sc/source/ui/view/dbfunc3.cxx
2466 index 3e5a627..df92a5e 100644
2467 --- sc/source/ui/view/dbfunc3.cxx
2468 +++ sc/source/ui/view/dbfunc3.cxx
2469 @@ -91,6 +91,10 @@ using ::com::sun::star::uno::Sequence;
2470 using ::com::sun::star::uno::Reference;
2471 using ::com::sun::star::uno::UNO_QUERY;
2472 using ::com::sun::star::beans::XPropertySet;
2473 +using ::com::sun::star::container::XNameAccess;
2474 +using ::com::sun::star::sheet::XDimensionsSupplier;
2475 +using ::rtl::OUString;
2476 +using ::rtl::OUStringBuffer;
2477 using ::std::auto_ptr;
2479 // STATIC DATA -----------------------------------------------------------
2480 @@ -1377,123 +1381,304 @@ void ScDBFunc::UngroupDataPilot()
2484 +OUString lcl_replaceMemberNameInSubtotal(const OUString& rSubtotal, const OUString& rMemberName)
2486 + sal_Int32 n = rSubtotal.getLength();
2487 + const sal_Unicode* p = rSubtotal.getStr();
2488 + OUStringBuffer aBuf, aWordBuf;
2489 + for (sal_Int32 i = 0; i < n; ++i)
2491 + sal_Unicode c = p[i];
2492 + if (c == sal_Unicode(' '))
2494 + OUString aWord = aWordBuf.makeStringAndClear();
2495 + if (aWord.equals(rMemberName))
2496 + aBuf.append(sal_Unicode('?'));
2497 + else
2498 + aBuf.append(aWord);
2499 + aBuf.append(c);
2501 + else
2502 + aWordBuf.append(c);
2505 + if (aWordBuf.getLength() > 0)
2507 + OUString aWord = aWordBuf.makeStringAndClear();
2508 + if (aWord.equals(rMemberName))
2509 + aBuf.append(sal_Unicode('?'));
2510 + else
2511 + aBuf.append(aWord);
2514 + return aBuf.makeStringAndClear();
2517 void ScDBFunc::DataPilotInput( const ScAddress& rPos, const String& rString )
2519 + using namespace ::com::sun::star::sheet;
2521 String aNewName( rString );
2523 ScDocument* pDoc = GetViewData()->GetDocument();
2524 ScDPObject* pDPObj = pDoc->GetDPAtCursor( rPos.Col(), rPos.Row(), rPos.Tab() );
2525 - if ( pDPObj )
2526 + if (!pDPObj)
2527 + return;
2529 + String aOldText;
2530 + pDoc->GetString( rPos.Col(), rPos.Row(), rPos.Tab(), aOldText );
2532 + if ( aOldText == rString )
2534 - String aOldText;
2535 - pDoc->GetString( rPos.Col(), rPos.Row(), rPos.Tab(), aOldText );
2536 + // nothing to do: silently exit
2537 + return;
2540 - if ( aOldText == rString )
2541 + USHORT nErrorId = 0;
2543 + pDPObj->BuildAllDimensionMembers();
2544 + ScDPSaveData aData( *pDPObj->GetSaveData() );
2545 + BOOL bChange = FALSE;
2547 + USHORT nOrient = DataPilotFieldOrientation_HIDDEN;
2548 + long nField = pDPObj->GetHeaderDim( rPos, nOrient );
2549 + if ( nField >= 0 )
2551 + // changing a field title
2552 + if ( aData.GetExistingDimensionData() )
2554 - // nothing to do: silently exit
2555 - return;
2557 + // only group dimensions can be renamed
2559 - USHORT nErrorId = 0;
2560 + ScDPDimensionSaveData* pDimData = aData.GetDimensionData();
2561 + ScDPSaveGroupDimension* pGroupDim = pDimData->GetNamedGroupDimAcc( aOldText );
2562 + if ( pGroupDim )
2564 + // valid name: not empty, no existing dimension (group or other)
2565 + if ( rString.Len() && !pDPObj->IsDimNameInUse(rString) )
2567 + pGroupDim->Rename( aNewName );
2569 - ScDPSaveData aData( *pDPObj->GetSaveData() );
2570 - BOOL bChange = FALSE;
2571 + // also rename in SaveData to preserve the field settings
2572 + ScDPSaveDimension* pSaveDim = aData.GetDimensionByName( aOldText );
2573 + pSaveDim->SetName( aNewName );
2575 - USHORT nOrient = sheet::DataPilotFieldOrientation_HIDDEN;
2576 - long nField = pDPObj->GetHeaderDim( rPos, nOrient );
2577 - if ( nField >= 0 )
2578 + bChange = TRUE;
2580 + else
2581 + nErrorId = STR_INVALIDNAME;
2584 + else if (nOrient == DataPilotFieldOrientation_COLUMN || nOrient == DataPilotFieldOrientation_ROW)
2586 - // changing a field title
2587 + BOOL bDataLayout = false;
2588 + String aDimName = pDPObj->GetDimName(nField, bDataLayout);
2589 + ScDPSaveDimension* pDim = bDataLayout ? aData.GetDataLayoutDimension() : aData.GetDimensionByName(aDimName);
2590 + if (pDim)
2592 + if (rString.Len())
2594 + if (rString.EqualsIgnoreCaseAscii(aDimName))
2595 + {
2596 + pDim->RemoveLayoutName();
2597 + bChange = true;
2599 + else if (!pDPObj->IsDimNameInUse(rString))
2601 + pDim->SetLayoutName(rString);
2602 + bChange = true;
2604 + else
2605 + nErrorId = STR_INVALIDNAME;
2607 + else
2608 + nErrorId = STR_INVALIDNAME;
2612 + else if (pDPObj->IsDataDescriptionCell(rPos))
2614 + // There is only one data dimension.
2615 + ScDPSaveDimension* pDim = aData.GetFirstDimension(sheet::DataPilotFieldOrientation_DATA);
2616 + if (pDim)
2618 + if (rString.Len())
2620 + if (rString.EqualsIgnoreCaseAscii(pDim->GetName()))
2622 + pDim->RemoveLayoutName();
2623 + bChange = true;
2625 + else if (!pDPObj->IsDimNameInUse(rString))
2627 + pDim->SetLayoutName(rString);
2628 + bChange = true;
2630 + else
2631 + nErrorId = STR_INVALIDNAME;
2633 + else
2634 + nErrorId = STR_INVALIDNAME;
2637 + else
2639 + // This is not a field header.
2640 + sheet::DataPilotTableHeaderData aPosData;
2641 + pDPObj->GetHeaderPositionData(rPos, aPosData);
2643 - if ( aData.GetExistingDimensionData() )
2644 + if ( (aPosData.Flags & MemberResultFlags::HASMEMBER) && aOldText.Len() )
2646 + if ( aData.GetExistingDimensionData() && !(aPosData.Flags & MemberResultFlags::SUBTOTAL))
2648 - // only group dimensions can be renamed
2649 + BOOL bIsDataLayout;
2650 + String aDimName = pDPObj->GetDimName( aPosData.Dimension, bIsDataLayout );
2652 ScDPDimensionSaveData* pDimData = aData.GetDimensionData();
2653 - ScDPSaveGroupDimension* pGroupDim = pDimData->GetNamedGroupDimAcc( aOldText );
2654 + ScDPSaveGroupDimension* pGroupDim = pDimData->GetNamedGroupDimAcc( aDimName );
2655 if ( pGroupDim )
2657 - // valid name: not empty, no existing dimension (group or other)
2658 - if ( aNewName.Len() && !pDPObj->IsDimNameInUse( aNewName ) )
2659 + // valid name: not empty, no existing group in this dimension
2660 + //! ignore case?
2661 + if ( aNewName.Len() && !pGroupDim->GetNamedGroup( aNewName ) )
2663 - pGroupDim->Rename( aNewName );
2664 + ScDPSaveGroupItem* pGroup = pGroupDim->GetNamedGroupAcc( aOldText );
2665 + if ( pGroup )
2666 + pGroup->Rename( aNewName ); // rename the existing group
2667 + else
2669 + // create a new group to replace the automatic group
2670 + ScDPSaveGroupItem aGroup( aNewName );
2671 + aGroup.AddElement( aOldText );
2672 + pGroupDim->AddGroupItem( aGroup );
2675 - // also rename in SaveData to preserve the field settings
2676 - ScDPSaveDimension* pSaveDim = aData.GetDimensionByName( aOldText );
2677 - pSaveDim->SetName( aNewName );
2678 + // in both cases also adjust savedata, to preserve member settings (show details)
2679 + ScDPSaveDimension* pSaveDim = aData.GetDimensionByName( aDimName );
2680 + ScDPSaveMember* pSaveMember = pSaveDim->GetExistingMemberByName( aOldText );
2681 + if ( pSaveMember )
2682 + pSaveMember->SetName( aNewName );
2684 bChange = TRUE;
2686 else
2687 nErrorId = STR_INVALIDNAME;
2692 - else
2694 - // renaming a group (item)?
2695 - // allow only on the item name itself - not on empty cells, not on subtotals
2697 - sheet::DataPilotTableHeaderData aPosData;
2698 - pDPObj->GetHeaderPositionData(rPos, aPosData);
2699 - if ( ( aPosData.Flags & sheet::MemberResultFlags::HASMEMBER ) &&
2700 - ! ( aPosData.Flags & sheet::MemberResultFlags::SUBTOTAL ) &&
2701 - aOldText.Len() )
2702 + else if ((aPosData.Flags & MemberResultFlags::GRANDTOTAL))
2704 - if ( aData.GetExistingDimensionData() )
2705 + aData.SetGrandTotalName(rString);
2706 + bChange = true;
2708 + else if (aPosData.Dimension >= 0 && aPosData.MemberName.getLength() > 0)
2710 + BOOL bDataLayout = false;
2711 + String aDimName = pDPObj->GetDimName(static_cast<long>(aPosData.Dimension), bDataLayout);
2712 + if (bDataLayout)
2714 - BOOL bIsDataLayout;
2715 - String aDimName = pDPObj->GetDimName( aPosData.Dimension, bIsDataLayout );
2716 + // data dimension
2717 + do
2719 + if ((aPosData.Flags & MemberResultFlags::SUBTOTAL))
2720 + break;
2722 + ScDPSaveDimension* pDim = aData.GetDimensionByName(aPosData.MemberName);
2723 + if (!pDim)
2724 + break;
2726 - ScDPDimensionSaveData* pDimData = aData.GetDimensionData();
2727 - ScDPSaveGroupDimension* pGroupDim = pDimData->GetNamedGroupDimAcc( aDimName );
2728 - if ( pGroupDim )
2729 + if (!rString.Len())
2731 + nErrorId = STR_INVALIDNAME;
2732 + break;
2735 + if (aPosData.MemberName.equalsIgnoreAsciiCase(rString))
2737 + pDim->RemoveLayoutName();
2738 + bChange = true;
2740 + else if (!pDPObj->IsDimNameInUse(rString))
2742 + pDim->SetLayoutName(rString);
2743 + bChange = true;
2745 + else
2746 + nErrorId = STR_INVALIDNAME;
2748 + while (false);
2750 + else
2752 + // field member
2753 + do
2755 - // valid name: not empty, no existing group in this dimension
2756 - //! ignore case?
2757 - if ( aNewName.Len() && !pGroupDim->GetNamedGroup( aNewName ) )
2758 + ScDPSaveDimension* pDim = aData.GetDimensionByName(aDimName);
2759 + if (!pDim)
2760 + break;
2762 + ScDPSaveMember* pMem = pDim->GetExistingMemberByName(aPosData.MemberName);
2763 + if (!pMem)
2764 + break;
2766 + if ((aPosData.Flags & MemberResultFlags::SUBTOTAL))
2768 - ScDPSaveGroupItem* pGroup = pGroupDim->GetNamedGroupAcc( aOldText );
2769 - if ( pGroup )
2770 - pGroup->Rename( aNewName ); // rename the existing group
2771 + // Change subtotal only when the table has one data dimension.
2772 + if (aData.GetDataDimensionCount() > 1)
2773 + break;
2775 + const OUString* pLayoutName = pMem->GetLayoutName();
2776 + String aMemberName;
2777 + if (pLayoutName)
2778 + aMemberName = *pLayoutName;
2779 else
2781 - // create a new group to replace the automatic group
2782 - ScDPSaveGroupItem aGroup( aNewName );
2783 - aGroup.AddElement( aOldText );
2784 - pGroupDim->AddGroupItem( aGroup );
2786 + aMemberName = aPosData.MemberName;
2788 - // in both cases also adjust savedata, to preserve member settings (show details)
2789 - ScDPSaveDimension* pSaveDim = aData.GetDimensionByName( aDimName );
2790 - ScDPSaveMember* pSaveMember = pSaveDim->GetExistingMemberByName( aOldText );
2791 - if ( pSaveMember )
2792 - pSaveMember->SetName( aNewName );
2794 - bChange = TRUE;
2795 + String aNew = lcl_replaceMemberNameInSubtotal(rString, aMemberName);
2796 + pDim->SetSubtotalName(aNew);
2797 + bChange = true;
2799 else
2800 - nErrorId = STR_INVALIDNAME;
2802 + // Check to make sure the member name isn't
2803 + // already used.
2804 + if (rString.Len())
2806 + if (rString.EqualsIgnoreCaseAscii(pMem->GetName()))
2808 + pMem->RemoveLayoutName();
2809 + bChange = true;
2811 + else if (!pDim->IsMemberNameInUse(rString))
2813 + pMem->SetLayoutName(rString);
2814 + bChange = true;
2816 + else
2817 + nErrorId = STR_INVALIDNAME;
2819 + else
2820 + nErrorId = STR_INVALIDNAME;
2823 + while (false);
2829 - if ( bChange )
2831 - // apply changes
2832 - ScDBDocFunc aFunc( *GetViewData()->GetDocShell() );
2833 - ScDPObject* pNewObj = new ScDPObject( *pDPObj );
2834 - pNewObj->SetSaveData( aData );
2835 - aFunc.DataPilotUpdate( pDPObj, pNewObj, TRUE, FALSE );
2836 - delete pNewObj;
2838 - else
2840 - if ( !nErrorId )
2841 - nErrorId = STR_ERR_DATAPILOT_INPUT;
2842 - ErrorMessage( nErrorId );
2844 + if ( bChange )
2846 + // apply changes
2847 + ScDBDocFunc aFunc( *GetViewData()->GetDocShell() );
2848 + ScDPObject* pNewObj = new ScDPObject( *pDPObj );
2849 + pNewObj->SetSaveData( aData );
2850 + aFunc.DataPilotUpdate( pDPObj, pNewObj, TRUE, FALSE );
2851 + delete pNewObj;
2853 + else
2855 + if ( !nErrorId )
2856 + nErrorId = STR_ERR_DATAPILOT_INPUT;
2857 + ErrorMessage( nErrorId );