Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include "xepivot.hxx"
30 : : #include <com/sun/star/sheet/DataPilotFieldSortInfo.hpp>
31 : : #include <com/sun/star/sheet/DataPilotFieldAutoShowInfo.hpp>
32 : : #include <com/sun/star/sheet/DataPilotFieldLayoutInfo.hpp>
33 : : #include <com/sun/star/sheet/DataPilotFieldReference.hpp>
34 : : #include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp>
35 : :
36 : : #include <algorithm>
37 : : #include <math.h>
38 : :
39 : : #include <rtl/math.hxx>
40 : : #include <tools/date.hxx>
41 : : #include <svl/zformat.hxx>
42 : : #include <sot/storage.hxx>
43 : : #include "document.hxx"
44 : : #include "dpobject.hxx"
45 : : #include "dpsave.hxx"
46 : : #include "dpdimsave.hxx"
47 : : #include "dpshttab.hxx"
48 : : #include "globstr.hrc"
49 : : #include "fapihelper.hxx"
50 : : #include "xestring.hxx"
51 : : #include "xelink.hxx"
52 : : #include "dputil.hxx"
53 : :
54 : : using namespace ::oox;
55 : :
56 : : using ::com::sun::star::sheet::DataPilotFieldOrientation;
57 : : using ::com::sun::star::sheet::DataPilotFieldOrientation_HIDDEN;
58 : : using ::com::sun::star::sheet::DataPilotFieldOrientation_ROW;
59 : : using ::com::sun::star::sheet::DataPilotFieldOrientation_COLUMN;
60 : : using ::com::sun::star::sheet::DataPilotFieldOrientation_PAGE;
61 : : using ::com::sun::star::sheet::DataPilotFieldOrientation_DATA;
62 : : using ::com::sun::star::sheet::GeneralFunction;
63 : : using ::com::sun::star::sheet::DataPilotFieldSortInfo;
64 : : using ::com::sun::star::sheet::DataPilotFieldAutoShowInfo;
65 : : using ::com::sun::star::sheet::DataPilotFieldLayoutInfo;
66 : : using ::com::sun::star::sheet::DataPilotFieldReference;
67 : : using ::rtl::OUString;
68 : :
69 : : using ::rtl::OString;
70 : : using ::rtl::OUString;
71 : : using ::rtl::OUStringBuffer;
72 : :
73 : : // ============================================================================
74 : : // Pivot cache
75 : : // ============================================================================
76 : :
77 : : namespace {
78 : :
79 : : // constants to track occurrence of specific data types
80 : : const sal_uInt16 EXC_PCITEM_DATA_STRING = 0x0001; /// String, empty, boolean, error.
81 : : const sal_uInt16 EXC_PCITEM_DATA_DOUBLE = 0x0002; /// Double with fraction.
82 : : const sal_uInt16 EXC_PCITEM_DATA_INTEGER = 0x0004; /// Integer, double without fraction.
83 : : const sal_uInt16 EXC_PCITEM_DATA_DATE = 0x0008; /// Date, time, date/time.
84 : :
85 : : /** Maps a bitfield consisting of EXC_PCITEM_DATA_* flags above to SXFIELD data type bitfield. */
86 : : static const sal_uInt16 spnPCItemFlags[] =
87 : : { // STR DBL INT DAT
88 : : EXC_SXFIELD_DATA_NONE, //
89 : : EXC_SXFIELD_DATA_STR, // x
90 : : EXC_SXFIELD_DATA_INT, // x
91 : : EXC_SXFIELD_DATA_STR_INT, // x x
92 : : EXC_SXFIELD_DATA_DBL, // x
93 : : EXC_SXFIELD_DATA_STR_DBL, // x x
94 : : EXC_SXFIELD_DATA_INT, // x x
95 : : EXC_SXFIELD_DATA_STR_INT, // x x x
96 : : EXC_SXFIELD_DATA_DATE, // x
97 : : EXC_SXFIELD_DATA_DATE_STR, // x x
98 : : EXC_SXFIELD_DATA_DATE_NUM, // x x
99 : : EXC_SXFIELD_DATA_DATE_STR, // x x x
100 : : EXC_SXFIELD_DATA_DATE_NUM, // x x
101 : : EXC_SXFIELD_DATA_DATE_STR, // x x x
102 : : EXC_SXFIELD_DATA_DATE_NUM, // x x x
103 : : EXC_SXFIELD_DATA_DATE_STR // x x x x
104 : : };
105 : :
106 : : } // namespace
107 : :
108 : : // ----------------------------------------------------------------------------
109 : :
110 : 0 : XclExpPCItem::XclExpPCItem( const String& rText ) :
111 : 0 : XclExpRecord( (rText.Len() > 0) ? EXC_ID_SXSTRING : EXC_ID_SXEMPTY, 0 ),
112 [ # # ][ # # ]: 0 : mnTypeFlag( EXC_PCITEM_DATA_STRING )
113 : : {
114 [ # # ]: 0 : if( rText.Len() )
115 [ # # ][ # # ]: 0 : SetText( rText );
116 : : else
117 [ # # ]: 0 : SetEmpty();
118 : 0 : }
119 : :
120 : 0 : XclExpPCItem::XclExpPCItem( double fValue ) :
121 [ # # ]: 0 : XclExpRecord( EXC_ID_SXDOUBLE, 8 )
122 : : {
123 [ # # ]: 0 : SetDouble( fValue );
124 : 0 : mnTypeFlag = (fValue - floor( fValue ) == 0.0) ?
125 [ # # ]: 0 : EXC_PCITEM_DATA_INTEGER : EXC_PCITEM_DATA_DOUBLE;
126 : 0 : }
127 : :
128 : 0 : XclExpPCItem::XclExpPCItem( const DateTime& rDateTime ) :
129 [ # # ]: 0 : XclExpRecord( EXC_ID_SXDATETIME, 8 )
130 : : {
131 [ # # ]: 0 : SetDateTime( rDateTime );
132 : 0 : mnTypeFlag = EXC_PCITEM_DATA_DATE;
133 : 0 : }
134 : :
135 : 0 : XclExpPCItem::XclExpPCItem( sal_Int16 nValue ) :
136 : : XclExpRecord( EXC_ID_SXINTEGER, 2 ),
137 [ # # ]: 0 : mnTypeFlag( EXC_PCITEM_DATA_INTEGER )
138 : : {
139 [ # # ]: 0 : SetInteger( nValue );
140 : 0 : }
141 : :
142 : 0 : XclExpPCItem::XclExpPCItem( bool bValue ) :
143 : : XclExpRecord( EXC_ID_SXBOOLEAN, 2 ),
144 [ # # ]: 0 : mnTypeFlag( EXC_PCITEM_DATA_STRING )
145 : : {
146 [ # # ]: 0 : SetBool( bValue );
147 : 0 : }
148 : :
149 : : // ----------------------------------------------------------------------------
150 : :
151 : 0 : bool XclExpPCItem::EqualsText( const rtl::OUString& rText ) const
152 : : {
153 [ # # ][ # # ]: 0 : return rText.isEmpty() ? IsEmpty() : (GetText() && (*GetText() == rText));
[ # # ]
154 : : }
155 : :
156 : 0 : bool XclExpPCItem::EqualsDouble( double fValue ) const
157 : : {
158 [ # # ][ # # ]: 0 : return GetDouble() && (*GetDouble() == fValue);
159 : : }
160 : :
161 : 0 : bool XclExpPCItem::EqualsDateTime( const DateTime& rDateTime ) const
162 : : {
163 [ # # ][ # # ]: 0 : return GetDateTime() && (*GetDateTime() == rDateTime);
164 : : }
165 : :
166 : 0 : bool XclExpPCItem::EqualsBool( bool bValue ) const
167 : : {
168 [ # # ][ # # ]: 0 : return GetBool() && (*GetBool() == bValue);
169 : : }
170 : :
171 : : // ----------------------------------------------------------------------------
172 : :
173 : 0 : void XclExpPCItem::WriteBody( XclExpStream& rStrm )
174 : : {
175 [ # # ]: 0 : if( const rtl::OUString* pText = GetText() )
176 : : {
177 [ # # ]: 0 : rStrm << XclExpString( *pText );
178 : : }
179 [ # # ]: 0 : else if( const double* pfValue = GetDouble() )
180 : : {
181 : 0 : rStrm << *pfValue;
182 : : }
183 [ # # ]: 0 : else if( const sal_Int16* pnValue = GetInteger() )
184 : : {
185 : 0 : rStrm << *pnValue;
186 : : }
187 [ # # ]: 0 : else if( const DateTime* pDateTime = GetDateTime() )
188 : : {
189 : 0 : sal_uInt16 nYear = static_cast< sal_uInt16 >( pDateTime->GetYear() );
190 : 0 : sal_uInt16 nMonth = static_cast< sal_uInt16 >( pDateTime->GetMonth() );
191 : 0 : sal_uInt8 nDay = static_cast< sal_uInt8 >( pDateTime->GetDay() );
192 : 0 : sal_uInt8 nHour = static_cast< sal_uInt8 >( pDateTime->GetHour() );
193 : 0 : sal_uInt8 nMin = static_cast< sal_uInt8 >( pDateTime->GetMin() );
194 : 0 : sal_uInt8 nSec = static_cast< sal_uInt8 >( pDateTime->GetSec() );
195 [ # # ]: 0 : if( nYear < 1900 ) { nYear = 1900; nMonth = 1; nDay = 0; }
196 : 0 : rStrm << nYear << nMonth << nDay << nHour << nMin << nSec;
197 : : }
198 [ # # ]: 0 : else if( const bool* pbValue = GetBool() )
199 : : {
200 [ # # ]: 0 : rStrm << static_cast< sal_uInt16 >( *pbValue ? 1 : 0 );
201 : : }
202 : : else
203 : : {
204 : : // nothing to do for SXEMPTY
205 : : OSL_ENSURE( IsEmpty(), "XclExpPCItem::WriteBody - no data found" );
206 : : }
207 : 0 : }
208 : :
209 : : // ============================================================================
210 : :
211 : 0 : XclExpPCField::XclExpPCField(
212 : : const XclExpRoot& rRoot, const XclExpPivotCache& rPCache, sal_uInt16 nFieldIdx,
213 : : const ScDPObject& rDPObj, const ScRange& rRange ) :
214 : : XclExpRecord( EXC_ID_SXFIELD ),
215 : : XclPCField( EXC_PCFIELD_STANDARD, nFieldIdx ),
216 : : XclExpRoot( rRoot ),
217 : : mrPCache( rPCache ),
218 [ # # ][ # # ]: 0 : mnTypeFlags( 0 )
[ # # ][ # # ]
[ # # ][ # # ]
219 : : {
220 : : // general settings for the standard field, insert all items from source range
221 [ # # ]: 0 : InitStandardField( rRange );
222 : :
223 : : // add special settings for inplace numeric grouping
224 [ # # ]: 0 : if( const ScDPSaveData* pSaveData = rDPObj.GetSaveData() )
225 : : {
226 [ # # ]: 0 : if( const ScDPDimensionSaveData* pSaveDimData = pSaveData->GetExistingDimensionData() )
227 : : {
228 [ # # ][ # # ]: 0 : if( const ScDPSaveNumGroupDimension* pNumGroupDim = pSaveDimData->GetNumGroupDim( GetFieldName() ) )
229 : : {
230 : 0 : const ScDPNumGroupInfo& rNumInfo = pNumGroupDim->GetInfo();
231 : 0 : const ScDPNumGroupInfo& rDateInfo = pNumGroupDim->GetDateInfo();
232 : : OSL_ENSURE( !rNumInfo.mbEnable || !rDateInfo.mbEnable,
233 : : "XclExpPCField::XclExpPCField - numeric and date grouping enabled" );
234 : :
235 [ # # ]: 0 : if( rNumInfo.mbEnable )
236 [ # # ]: 0 : InitNumGroupField( rDPObj, rNumInfo );
237 [ # # ]: 0 : else if( rDateInfo.mbEnable )
238 [ # # ]: 0 : InitDateGroupField( rDPObj, rDateInfo, pNumGroupDim->GetDatePart() );
239 : : }
240 : : }
241 : : }
242 : :
243 : : // final settings (flags, item numbers)
244 [ # # ]: 0 : Finalize();
245 : 0 : }
246 : :
247 : 0 : XclExpPCField::XclExpPCField(
248 : : const XclExpRoot& rRoot, const XclExpPivotCache& rPCache, sal_uInt16 nFieldIdx,
249 : : const ScDPObject& rDPObj, const ScDPSaveGroupDimension& rGroupDim, const XclExpPCField& rBaseField ) :
250 : : XclExpRecord( EXC_ID_SXFIELD ),
251 : : XclPCField( EXC_PCFIELD_STDGROUP, nFieldIdx ),
252 : : XclExpRoot( rRoot ),
253 : : mrPCache( rPCache ),
254 [ # # ][ # # ]: 0 : mnTypeFlags( 0 )
[ # # ][ # # ]
[ # # ][ # # ]
255 : : {
256 : : // add base field info (always using first base field, not predecessor of this field) ***
257 : : OSL_ENSURE( rBaseField.GetFieldName() == rGroupDim.GetSourceDimName(),
258 : : "XclExpPCField::FillFromGroup - wrong base cache field" );
259 : 0 : maFieldInfo.maName = rGroupDim.GetGroupDimName();
260 : 0 : maFieldInfo.mnGroupBase = rBaseField.GetFieldIndex();
261 : :
262 : : // add standard group info or date group info
263 : 0 : const ScDPNumGroupInfo& rDateInfo = rGroupDim.GetDateInfo();
264 [ # # ][ # # ]: 0 : if( rDateInfo.mbEnable && (rGroupDim.GetDatePart() != 0) )
[ # # ]
265 [ # # ]: 0 : InitDateGroupField( rDPObj, rDateInfo, rGroupDim.GetDatePart() );
266 : : else
267 [ # # ]: 0 : InitStdGroupField( rBaseField, rGroupDim );
268 : :
269 : : // final settings (flags, item numbers)
270 [ # # ]: 0 : Finalize();
271 : 0 : }
272 : :
273 [ # # ][ # # ]: 0 : XclExpPCField::~XclExpPCField()
[ # # ][ # # ]
[ # # ]
274 : : {
275 [ # # ]: 0 : }
276 : :
277 : 0 : void XclExpPCField::SetGroupChildField( const XclExpPCField& rChildField )
278 : : {
279 : : OSL_ENSURE( !::get_flag( maFieldInfo.mnFlags, EXC_SXFIELD_HASCHILD ),
280 : : "XclExpPCField::SetGroupChildIndex - field already has a grouping child field" );
281 : 0 : ::set_flag( maFieldInfo.mnFlags, EXC_SXFIELD_HASCHILD );
282 : 0 : maFieldInfo.mnGroupChild = rChildField.GetFieldIndex();
283 : 0 : }
284 : :
285 : 0 : sal_uInt16 XclExpPCField::GetItemCount() const
286 : : {
287 : 0 : return static_cast< sal_uInt16 >( GetVisItemList().GetSize() );
288 : : }
289 : :
290 : 0 : const XclExpPCItem* XclExpPCField::GetItem( sal_uInt16 nItemIdx ) const
291 : : {
292 : 0 : return GetVisItemList().GetRecord( nItemIdx ).get();
293 : : }
294 : :
295 : 0 : sal_uInt16 XclExpPCField::GetItemIndex( const rtl::OUString& rItemName ) const
296 : : {
297 : 0 : const XclExpPCItemList& rItemList = GetVisItemList();
298 [ # # ]: 0 : for( size_t nPos = 0, nSize = rItemList.GetSize(); nPos < nSize; ++nPos )
299 [ # # ]: 0 : if( rItemList.GetRecord( nPos )->ConvertToText() == rItemName )
300 : 0 : return static_cast< sal_uInt16 >( nPos );
301 : 0 : return EXC_PC_NOITEM;
302 : : }
303 : :
304 : 0 : sal_Size XclExpPCField::GetIndexSize() const
305 : : {
306 [ # # ]: 0 : return Has16BitIndexes() ? 2 : 1;
307 : : }
308 : :
309 : 0 : void XclExpPCField::WriteIndex( XclExpStream& rStrm, sal_uInt32 nSrcRow ) const
310 : : {
311 : : // only standard fields write item indexes
312 [ # # ]: 0 : if( nSrcRow < maIndexVec.size() )
313 : : {
314 : 0 : sal_uInt16 nIndex = maIndexVec[ nSrcRow ];
315 [ # # ]: 0 : if( Has16BitIndexes() )
316 : 0 : rStrm << nIndex;
317 : : else
318 : 0 : rStrm << static_cast< sal_uInt8 >( nIndex );
319 : : }
320 : 0 : }
321 : :
322 : 0 : void XclExpPCField::Save( XclExpStream& rStrm )
323 : : {
324 : : OSL_ENSURE( IsSupportedField(), "XclExpPCField::Save - unknown field type" );
325 : : // SXFIELD
326 : 0 : XclExpRecord::Save( rStrm );
327 : : // SXFDBTYPE
328 [ # # ]: 0 : XclExpUInt16Record( EXC_ID_SXFDBTYPE, EXC_SXFDBTYPE_DEFAULT ).Save( rStrm );
329 : : // list of grouping items
330 : 0 : maGroupItemList.Save( rStrm );
331 : : // SXGROUPINFO
332 : 0 : WriteSxgroupinfo( rStrm );
333 : : // SXNUMGROUP and additional grouping items (grouping limit settings)
334 : 0 : WriteSxnumgroup( rStrm );
335 : : // list of original items
336 : 0 : maOrigItemList.Save( rStrm );
337 : 0 : }
338 : :
339 : : // private --------------------------------------------------------------------
340 : :
341 : 0 : const XclExpPCField::XclExpPCItemList& XclExpPCField::GetVisItemList() const
342 : : {
343 : : OSL_ENSURE( IsStandardField() == maGroupItemList.IsEmpty(),
344 : : "XclExpPCField::GetVisItemList - unexpected additional items in standard field" );
345 [ # # ]: 0 : return IsStandardField() ? maOrigItemList : maGroupItemList;
346 : : }
347 : :
348 : 0 : void XclExpPCField::InitStandardField( const ScRange& rRange )
349 : : {
350 : : OSL_ENSURE( IsStandardField(), "XclExpPCField::InitStandardField - only for standard fields" );
351 : : OSL_ENSURE( rRange.aStart.Col() == rRange.aEnd.Col(), "XclExpPCField::InitStandardField - cell range with multiple columns" );
352 : :
353 : 0 : ScDocument& rDoc = GetDoc();
354 [ # # ]: 0 : SvNumberFormatter& rFormatter = GetFormatter();
355 : :
356 : : // field name is in top cell of the range
357 : 0 : ScAddress aPos( rRange.aStart );
358 [ # # ]: 0 : rDoc.GetString( aPos.Col(), aPos.Row(), aPos.Tab(), maFieldInfo.maName );
359 : : // #i76047# maximum field name length in pivot cache is 255
360 [ # # ]: 0 : if (maFieldInfo.maName.getLength() > EXC_PC_MAXSTRLEN)
361 : 0 : maFieldInfo.maName = maFieldInfo.maName.copy(0, EXC_PC_MAXSTRLEN);
362 : :
363 : : // loop over all cells, create pivot cache items
364 [ # # ][ # # ]: 0 : for( aPos.IncRow(); (aPos.Row() <= rRange.aEnd.Row()) && (maOrigItemList.GetSize() < EXC_PC_MAXITEMCOUNT); aPos.IncRow() )
[ # # ][ # # ]
[ # # ]
365 : : {
366 [ # # ][ # # ]: 0 : if( rDoc.HasValueData( aPos.Col(), aPos.Row(), aPos.Tab() ) )
367 : : {
368 [ # # ]: 0 : double fValue = rDoc.GetValue( aPos );
369 [ # # ][ # # ]: 0 : short nFmtType = rFormatter.GetType( rDoc.GetNumberFormat( aPos ) );
370 [ # # ]: 0 : if( nFmtType == NUMBERFORMAT_LOGICAL )
371 [ # # ]: 0 : InsertOrigBoolItem( fValue != 0 );
372 [ # # ]: 0 : else if( nFmtType & NUMBERFORMAT_DATETIME )
373 [ # # ][ # # ]: 0 : InsertOrigDateTimeItem( GetDateTimeFromDouble( ::std::max( fValue, 0.0 ) ) );
[ # # ]
374 : : else
375 [ # # ]: 0 : InsertOrigDoubleItem( fValue );
376 : : }
377 : : else
378 : : {
379 [ # # ]: 0 : String aText;
380 [ # # ]: 0 : rDoc.GetString( aPos.Col(), aPos.Row(), aPos.Tab(), aText );
381 [ # # ][ # # ]: 0 : InsertOrigTextItem( aText );
382 : : }
383 : : }
384 : 0 : }
385 : :
386 : 0 : void XclExpPCField::InitStdGroupField( const XclExpPCField& rBaseField, const ScDPSaveGroupDimension& rGroupDim )
387 : : {
388 : : OSL_ENSURE( IsGroupField(), "XclExpPCField::InitStdGroupField - only for standard grouping fields" );
389 : :
390 : 0 : maFieldInfo.mnBaseItems = rBaseField.GetItemCount();
391 : 0 : maGroupOrder.resize( maFieldInfo.mnBaseItems, EXC_PC_NOITEM );
392 : :
393 : : // loop over all groups of this field
394 [ # # ]: 0 : for( long nGroupIdx = 0, nGroupCount = rGroupDim.GetGroupCount(); nGroupIdx < nGroupCount; ++nGroupIdx )
395 : : {
396 [ # # ]: 0 : if( const ScDPSaveGroupItem* pGroupItem = rGroupDim.GetGroupByIndex( nGroupIdx ) )
397 : : {
398 : : // the index of the new item containing the grouping name
399 : 0 : sal_uInt16 nGroupItemIdx = EXC_PC_NOITEM;
400 : : // loop over all elements of one group
401 [ # # ]: 0 : for( size_t nElemIdx = 0, nElemCount = pGroupItem->GetElementCount(); nElemIdx < nElemCount; ++nElemIdx )
402 : : {
403 [ # # ]: 0 : if (const rtl::OUString* pElemName = pGroupItem->GetElementByIndex(nElemIdx))
404 : : {
405 : : // try to find the item that is part of the group in the base field
406 : 0 : sal_uInt16 nBaseItemIdx = rBaseField.GetItemIndex( *pElemName );
407 [ # # ]: 0 : if( nBaseItemIdx < maFieldInfo.mnBaseItems )
408 : : {
409 : : // add group name item only if there are any valid base items
410 [ # # ]: 0 : if( nGroupItemIdx == EXC_PC_NOITEM )
411 [ # # ][ # # ]: 0 : nGroupItemIdx = InsertGroupItem( new XclExpPCItem( pGroupItem->GetGroupName() ) );
[ # # ]
412 : 0 : maGroupOrder[ nBaseItemIdx ] = nGroupItemIdx;
413 : : }
414 : : }
415 : : }
416 : : }
417 : : }
418 : :
419 : : // add items and base item indexes of all ungrouped elements
420 [ # # ]: 0 : for( sal_uInt16 nBaseItemIdx = 0; nBaseItemIdx < maFieldInfo.mnBaseItems; ++nBaseItemIdx )
421 : : // items that are not part of a group still have the EXC_PC_NOITEM entry
422 [ # # ]: 0 : if( maGroupOrder[ nBaseItemIdx ] == EXC_PC_NOITEM )
423 : : // try to find the base item
424 [ # # ]: 0 : if( const XclExpPCItem* pBaseItem = rBaseField.GetItem( nBaseItemIdx ) )
425 : : // create a clone of the base item, insert its index into item order list
426 [ # # ]: 0 : maGroupOrder[ nBaseItemIdx ] = InsertGroupItem( new XclExpPCItem( *pBaseItem ) );
427 : 0 : }
428 : :
429 : 0 : void XclExpPCField::InitNumGroupField( const ScDPObject& rDPObj, const ScDPNumGroupInfo& rNumInfo )
430 : : {
431 : : OSL_ENSURE( IsStandardField(), "XclExpPCField::InitNumGroupField - only for standard fields" );
432 : : OSL_ENSURE( rNumInfo.mbEnable, "XclExpPCField::InitNumGroupField - numeric grouping not enabled" );
433 : :
434 : : // new field type, date type, limit settings (min/max/step/auto)
435 [ # # ]: 0 : if( rNumInfo.mbDateValues )
436 : : {
437 : : // special case: group by days with step count
438 : 0 : meFieldType = EXC_PCFIELD_DATEGROUP;
439 : 0 : maNumGroupInfo.SetScDateType( com::sun::star::sheet::DataPilotFieldGroupBy::DAYS );
440 : 0 : SetDateGroupLimit( rNumInfo, true );
441 : : }
442 : : else
443 : : {
444 : 0 : meFieldType = EXC_PCFIELD_NUMGROUP;
445 : 0 : maNumGroupInfo.SetNumType();
446 : 0 : SetNumGroupLimit( rNumInfo );
447 : : }
448 : :
449 : : // generate visible items
450 : 0 : InsertNumDateGroupItems( rDPObj, rNumInfo );
451 : 0 : }
452 : :
453 : 0 : void XclExpPCField::InitDateGroupField( const ScDPObject& rDPObj, const ScDPNumGroupInfo& rDateInfo, sal_Int32 nDatePart )
454 : : {
455 : : OSL_ENSURE( IsStandardField() || IsStdGroupField(), "XclExpPCField::InitDateGroupField - only for standard fields" );
456 : : OSL_ENSURE( rDateInfo.mbEnable, "XclExpPCField::InitDateGroupField - date grouping not enabled" );
457 : :
458 : : // new field type
459 [ # # ]: 0 : meFieldType = IsStandardField() ? EXC_PCFIELD_DATEGROUP : EXC_PCFIELD_DATECHILD;
460 : :
461 : : // date type, limit settings (min/max/step/auto)
462 : 0 : maNumGroupInfo.SetScDateType( nDatePart );
463 : 0 : SetDateGroupLimit( rDateInfo, false );
464 : :
465 : : // generate visible items
466 : 0 : InsertNumDateGroupItems( rDPObj, rDateInfo, nDatePart );
467 : 0 : }
468 : :
469 : 0 : void XclExpPCField::InsertItemArrayIndex( size_t nListPos )
470 : : {
471 : : OSL_ENSURE( IsStandardField(), "XclExpPCField::InsertItemArrayIndex - only for standard fields" );
472 [ # # ]: 0 : maIndexVec.push_back( static_cast< sal_uInt16 >( nListPos ) );
473 : 0 : }
474 : :
475 : 0 : void XclExpPCField::InsertOrigItem( XclExpPCItem* pNewItem )
476 : : {
477 : 0 : size_t nItemIdx = maOrigItemList.GetSize();
478 : 0 : maOrigItemList.AppendNewRecord( pNewItem );
479 : 0 : InsertItemArrayIndex( nItemIdx );
480 : 0 : mnTypeFlags |= pNewItem->GetTypeFlag();
481 : 0 : }
482 : :
483 : 0 : void XclExpPCField::InsertOrigTextItem( const String& rText )
484 : : {
485 : 0 : size_t nPos = 0;
486 : 0 : bool bFound = false;
487 : : // #i76047# maximum item text length in pivot cache is 255
488 [ # # ][ # # ]: 0 : String aShortText( rText, 0, ::std::min( rText.Len(), EXC_PC_MAXSTRLEN ) );
489 [ # # ][ # # ]: 0 : for( size_t nSize = maOrigItemList.GetSize(); !bFound && (nPos < nSize); ++nPos )
[ # # ]
490 [ # # ][ # # ]: 0 : if( (bFound = maOrigItemList.GetRecord( nPos )->EqualsText( aShortText )) == true )
[ # # ][ # # ]
[ # # ]
491 [ # # ]: 0 : InsertItemArrayIndex( nPos );
492 [ # # ]: 0 : if( !bFound )
493 [ # # ][ # # ]: 0 : InsertOrigItem( new XclExpPCItem( aShortText ) );
[ # # ][ # # ]
494 : 0 : }
495 : :
496 : 0 : void XclExpPCField::InsertOrigDoubleItem( double fValue )
497 : : {
498 : 0 : size_t nPos = 0;
499 : 0 : bool bFound = false;
500 [ # # ][ # # ]: 0 : for( size_t nSize = maOrigItemList.GetSize(); !bFound && (nPos < nSize); ++nPos )
[ # # ]
501 [ # # ][ # # ]: 0 : if( (bFound = maOrigItemList.GetRecord( nPos )->EqualsDouble( fValue )) == true )
502 : 0 : InsertItemArrayIndex( nPos );
503 [ # # ]: 0 : if( !bFound )
504 [ # # ]: 0 : InsertOrigItem( new XclExpPCItem( fValue ) );
505 : 0 : }
506 : :
507 : 0 : void XclExpPCField::InsertOrigDateTimeItem( const DateTime& rDateTime )
508 : : {
509 : 0 : size_t nPos = 0;
510 : 0 : bool bFound = false;
511 [ # # ][ # # ]: 0 : for( size_t nSize = maOrigItemList.GetSize(); !bFound && (nPos < nSize); ++nPos )
[ # # ]
512 [ # # ][ # # ]: 0 : if( (bFound = maOrigItemList.GetRecord( nPos )->EqualsDateTime( rDateTime )) == true )
513 : 0 : InsertItemArrayIndex( nPos );
514 [ # # ]: 0 : if( !bFound )
515 [ # # ]: 0 : InsertOrigItem( new XclExpPCItem( rDateTime ) );
516 : 0 : }
517 : :
518 : 0 : void XclExpPCField::InsertOrigBoolItem( bool bValue )
519 : : {
520 : 0 : size_t nPos = 0;
521 : 0 : bool bFound = false;
522 [ # # ][ # # ]: 0 : for( size_t nSize = maOrigItemList.GetSize(); !bFound && (nPos < nSize); ++nPos )
[ # # ]
523 [ # # ][ # # ]: 0 : if( (bFound = maOrigItemList.GetRecord( nPos )->EqualsBool( bValue )) == true )
524 : 0 : InsertItemArrayIndex( nPos );
525 [ # # ]: 0 : if( !bFound )
526 [ # # ]: 0 : InsertOrigItem( new XclExpPCItem( bValue ) );
527 : 0 : }
528 : :
529 : 0 : sal_uInt16 XclExpPCField::InsertGroupItem( XclExpPCItem* pNewItem )
530 : : {
531 : 0 : maGroupItemList.AppendNewRecord( pNewItem );
532 : 0 : return static_cast< sal_uInt16 >( maGroupItemList.GetSize() - 1 );
533 : : }
534 : :
535 : 0 : void XclExpPCField::InsertNumDateGroupItems( const ScDPObject& rDPObj, const ScDPNumGroupInfo& rNumInfo, sal_Int32 nDatePart )
536 : : {
537 : : OSL_ENSURE( rDPObj.GetSheetDesc(), "XclExpPCField::InsertNumDateGroupItems - cannot generate element list" );
538 [ # # ]: 0 : if( const ScSheetSourceDesc* pSrcDesc = rDPObj.GetSheetDesc() )
539 : : {
540 : : // get the string collection with original source elements
541 : 0 : const ScDPSaveData* pSaveData = rDPObj.GetSaveData();
542 : 0 : const ScDPDimensionSaveData* pDimData = NULL;
543 [ # # ]: 0 : if (pSaveData)
544 : 0 : pDimData = pSaveData->GetExistingDimensionData();
545 : :
546 [ # # ]: 0 : const ScDPCache* pCache = pSrcDesc->CreateCache(pDimData);
547 [ # # ]: 0 : if (!pCache)
548 : 0 : return;
549 : :
550 [ # # ]: 0 : ScSheetDPData aDPData(GetDocPtr(), *pSrcDesc, pCache);
551 : 0 : long nDim = GetFieldIndex();
552 [ # # ][ # # ]: 0 : const std::vector< SCROW > aOrignial = aDPData.GetColumnEntries(nDim);
553 : : // get the string collection with generated grouping elements
554 [ # # ]: 0 : ScDPNumGroupDimension aTmpDim( rNumInfo );
555 [ # # ]: 0 : if( nDatePart != 0 )
556 [ # # ]: 0 : aTmpDim.SetDateDimension();
557 : : const std::vector<SCROW>& aMemberIds = aTmpDim.GetNumEntries(
558 [ # # ]: 0 : static_cast<SCCOL>(nDim), pCache);
559 [ # # ]: 0 : for ( size_t nIdx = 0 ; nIdx < aMemberIds.size(); nIdx++ )
560 : : {
561 [ # # ][ # # ]: 0 : const ScDPItemData* pData = aDPData.GetMemberById(nDim , aMemberIds[nIdx]);
562 [ # # ]: 0 : if ( pData )
563 : : {
564 [ # # ]: 0 : rtl::OUString aStr = pCache->GetFormattedString(nDim, *pData);
565 [ # # ][ # # ]: 0 : InsertGroupItem(new XclExpPCItem(aStr));
[ # # ][ # # ]
[ # # ]
566 : : }
567 [ # # ][ # # ]: 0 : }
568 : : }
569 : : }
570 : :
571 : 0 : void XclExpPCField::SetNumGroupLimit( const ScDPNumGroupInfo& rNumInfo )
572 : : {
573 : 0 : ::set_flag( maNumGroupInfo.mnFlags, EXC_SXNUMGROUP_AUTOMIN, rNumInfo.mbAutoStart );
574 : 0 : ::set_flag( maNumGroupInfo.mnFlags, EXC_SXNUMGROUP_AUTOMAX, rNumInfo.mbAutoEnd );
575 [ # # ]: 0 : maNumGroupLimits.AppendNewRecord( new XclExpPCItem( rNumInfo.mfStart ) );
576 [ # # ]: 0 : maNumGroupLimits.AppendNewRecord( new XclExpPCItem( rNumInfo.mfEnd ) );
577 [ # # ]: 0 : maNumGroupLimits.AppendNewRecord( new XclExpPCItem( rNumInfo.mfStep ) );
578 : 0 : }
579 : :
580 : 0 : void XclExpPCField::SetDateGroupLimit( const ScDPNumGroupInfo& rDateInfo, bool bUseStep )
581 : : {
582 : 0 : ::set_flag( maNumGroupInfo.mnFlags, EXC_SXNUMGROUP_AUTOMIN, rDateInfo.mbAutoStart );
583 : 0 : ::set_flag( maNumGroupInfo.mnFlags, EXC_SXNUMGROUP_AUTOMAX, rDateInfo.mbAutoEnd );
584 [ # # ][ # # ]: 0 : maNumGroupLimits.AppendNewRecord( new XclExpPCItem( GetDateTimeFromDouble( rDateInfo.mfStart ) ) );
[ # # ]
585 [ # # ][ # # ]: 0 : maNumGroupLimits.AppendNewRecord( new XclExpPCItem( GetDateTimeFromDouble( rDateInfo.mfEnd ) ) );
[ # # ]
586 [ # # ]: 0 : sal_Int16 nStep = bUseStep ? limit_cast< sal_Int16 >( rDateInfo.mfStep, 1, SAL_MAX_INT16 ) : 1;
587 [ # # ]: 0 : maNumGroupLimits.AppendNewRecord( new XclExpPCItem( nStep ) );
588 : 0 : }
589 : :
590 : 0 : void XclExpPCField::Finalize()
591 : : {
592 : : // flags
593 : 0 : ::set_flag( maFieldInfo.mnFlags, EXC_SXFIELD_HASITEMS, !GetVisItemList().IsEmpty() );
594 : : // Excel writes long indexes even for 0x0100 items (indexes from 0x00 to 0xFF)
595 : 0 : ::set_flag( maFieldInfo.mnFlags, EXC_SXFIELD_16BIT, maOrigItemList.GetSize() >= 0x0100 );
596 [ # # ][ # # ]: 0 : ::set_flag( maFieldInfo.mnFlags, EXC_SXFIELD_NUMGROUP, IsNumGroupField() || IsDateGroupField() );
597 : : /* mnTypeFlags is updated in all Insert***Item() functions. Now the flags
598 : : for the current combination of item types is added to the flags. */
599 : 0 : ::set_flag( maFieldInfo.mnFlags, spnPCItemFlags[ mnTypeFlags ] );
600 : :
601 : : // item count fields
602 : 0 : maFieldInfo.mnVisItems = static_cast< sal_uInt16 >( GetVisItemList().GetSize() );
603 : 0 : maFieldInfo.mnGroupItems = static_cast< sal_uInt16 >( maGroupItemList.GetSize() );
604 : : // maFieldInfo.mnBaseItems set in InitStdGroupField()
605 : 0 : maFieldInfo.mnOrigItems = static_cast< sal_uInt16 >( maOrigItemList.GetSize() );
606 : 0 : }
607 : :
608 : 0 : void XclExpPCField::WriteSxnumgroup( XclExpStream& rStrm )
609 : : {
610 [ # # ][ # # ]: 0 : if( IsNumGroupField() || IsDateGroupField() )
[ # # ]
611 : : {
612 : : // SXNUMGROUP record
613 : 0 : rStrm.StartRecord( EXC_ID_SXNUMGROUP, 2 );
614 : 0 : rStrm << maNumGroupInfo;
615 : 0 : rStrm.EndRecord();
616 : :
617 : : // limits (min/max/step) for numeric grouping
618 : : OSL_ENSURE( maNumGroupLimits.GetSize() == 3,
619 : : "XclExpPCField::WriteSxnumgroup - missing numeric grouping limits" );
620 : 0 : maNumGroupLimits.Save( rStrm );
621 : : }
622 : 0 : }
623 : :
624 : 0 : void XclExpPCField::WriteSxgroupinfo( XclExpStream& rStrm )
625 : : {
626 : : OSL_ENSURE( IsStdGroupField() != maGroupOrder.empty(),
627 : : "XclExpPCField::WriteSxgroupinfo - missing grouping info" );
628 [ # # ][ # # ]: 0 : if( IsStdGroupField() && !maGroupOrder.empty() )
[ # # ]
629 : : {
630 : 0 : rStrm.StartRecord( EXC_ID_SXGROUPINFO, 2 * maGroupOrder.size() );
631 [ # # ][ # # ]: 0 : for( ScfUInt16Vec::const_iterator aIt = maGroupOrder.begin(), aEnd = maGroupOrder.end(); aIt != aEnd; ++aIt )
[ # # ][ # # ]
[ # # ]
632 [ # # ][ # # ]: 0 : rStrm << *aIt;
633 : 0 : rStrm.EndRecord();
634 : : }
635 : 0 : }
636 : :
637 : 0 : void XclExpPCField::WriteBody( XclExpStream& rStrm )
638 : : {
639 : 0 : rStrm << maFieldInfo;
640 : 0 : }
641 : :
642 : : // ============================================================================
643 : :
644 : 0 : XclExpPivotCache::XclExpPivotCache( const XclExpRoot& rRoot, const ScDPObject& rDPObj, sal_uInt16 nListIdx ) :
645 : : XclExpRoot( rRoot ),
646 : : mnListIdx( nListIdx ),
647 [ # # ][ # # ]: 0 : mbValid( false )
648 : : {
649 : : // source from sheet only
650 [ # # ]: 0 : if( const ScSheetSourceDesc* pSrcDesc = rDPObj.GetSheetDesc() )
651 : : {
652 : : /* maOrigSrcRange: Range received from the DataPilot object.
653 : : maExpSrcRange: Range written to the DCONREF record.
654 : : maDocSrcRange: Range used to get source data from Calc document.
655 : : This range may be shorter than maExpSrcRange to improve export
656 : : performance (#i22541#). */
657 [ # # ]: 0 : maOrigSrcRange = maExpSrcRange = maDocSrcRange = pSrcDesc->GetSourceRange();
658 [ # # ]: 0 : maSrcRangeName = pSrcDesc->GetRangeName();
659 : :
660 : : // internal sheet data only
661 : 0 : SCTAB nScTab = maExpSrcRange.aStart.Tab();
662 [ # # ][ # # ]: 0 : if( (nScTab == maExpSrcRange.aEnd.Tab()) && GetTabInfo().IsExportTab( nScTab ) )
[ # # ][ # # ]
[ # # ]
663 : : {
664 : : // ValidateRange() restricts source range to valid Excel limits
665 [ # # ][ # # ]: 0 : if( GetAddressConverter().ValidateRange( maExpSrcRange, true ) )
[ # # ]
666 : : {
667 : : // #i22541# skip empty cell areas (performance)
668 : : SCCOL nDocCol1, nDocCol2;
669 : : SCROW nDocRow1, nDocRow2;
670 [ # # ]: 0 : GetDoc().GetDataStart( nScTab, nDocCol1, nDocRow1 );
671 [ # # ]: 0 : GetDoc().GetPrintArea( nScTab, nDocCol2, nDocRow2, false );
672 : 0 : SCCOL nSrcCol1 = maExpSrcRange.aStart.Col();
673 : 0 : SCROW nSrcRow1 = maExpSrcRange.aStart.Row();
674 : 0 : SCCOL nSrcCol2 = maExpSrcRange.aEnd.Col();
675 : 0 : SCROW nSrcRow2 = maExpSrcRange.aEnd.Row();
676 : :
677 : : // #i22541# do not store index list for too big ranges
678 [ # # ]: 0 : if( 2 * (nDocRow2 - nDocRow1) < (nSrcRow2 - nSrcRow1) )
679 : 0 : ::set_flag( maPCInfo.mnFlags, EXC_SXDB_SAVEDATA, false );
680 : :
681 : : // adjust row indexes, keep one row of empty area to surely have the empty cache item
682 [ # # ]: 0 : if( nSrcRow1 < nDocRow1 )
683 : 0 : nSrcRow1 = nDocRow1 - 1;
684 [ # # ]: 0 : if( nSrcRow2 > nDocRow2 )
685 : 0 : nSrcRow2 = nDocRow2 + 1;
686 : :
687 [ # # ]: 0 : maDocSrcRange.aStart.SetCol( ::std::max( nDocCol1, nSrcCol1 ) );
688 : 0 : maDocSrcRange.aStart.SetRow( nSrcRow1 );
689 [ # # ]: 0 : maDocSrcRange.aEnd.SetCol( ::std::min( nDocCol2, nSrcCol2 ) );
690 : 0 : maDocSrcRange.aEnd.SetRow( nSrcRow2 );
691 : :
692 [ # # ]: 0 : GetDoc().GetName( nScTab, maTabName );
693 : 0 : maPCInfo.mnSrcRecs = static_cast< sal_uInt32 >( maExpSrcRange.aEnd.Row() - maExpSrcRange.aStart.Row() );
694 : 0 : maPCInfo.mnStrmId = nListIdx + 1;
695 : 0 : maPCInfo.mnSrcType = EXC_SXDB_SRC_SHEET;
696 : :
697 [ # # ]: 0 : AddFields( rDPObj );
698 : :
699 : 0 : mbValid = true;
700 : : }
701 : : }
702 : : }
703 : 0 : }
704 : :
705 : 0 : bool XclExpPivotCache::HasItemIndexList() const
706 : : {
707 : 0 : return ::get_flag( maPCInfo.mnFlags, EXC_SXDB_SAVEDATA );
708 : : }
709 : :
710 : 0 : sal_uInt16 XclExpPivotCache::GetFieldCount() const
711 : : {
712 : 0 : return static_cast< sal_uInt16 >( maFieldList.GetSize() );
713 : : }
714 : :
715 : 0 : const XclExpPCField* XclExpPivotCache::GetField( sal_uInt16 nFieldIdx ) const
716 : : {
717 : 0 : return maFieldList.GetRecord( nFieldIdx ).get();
718 : : }
719 : :
720 : 0 : bool XclExpPivotCache::HasAddFields() const
721 : : {
722 : : // pivot cache can be shared, if there are no additional cache fields
723 : 0 : return maPCInfo.mnStdFields < maPCInfo.mnTotalFields;
724 : : }
725 : :
726 : 0 : bool XclExpPivotCache::HasEqualDataSource( const ScDPObject& rDPObj ) const
727 : : {
728 : : /* For now, only sheet sources are supported, therefore it is enough to
729 : : compare the ScSheetSourceDesc. Later, there should be done more complicated
730 : : comparisons regarding the source type of rDPObj and this cache. */
731 [ # # ]: 0 : if( const ScSheetSourceDesc* pSrcDesc = rDPObj.GetSheetDesc() )
732 : 0 : return pSrcDesc->GetSourceRange() == maOrigSrcRange;
733 : 0 : return false;
734 : : }
735 : :
736 : 0 : void XclExpPivotCache::Save( XclExpStream& rStrm )
737 : : {
738 : : OSL_ENSURE( mbValid, "XclExpPivotCache::Save - invalid pivot cache" );
739 : : // SXIDSTM
740 [ # # ]: 0 : XclExpUInt16Record( EXC_ID_SXIDSTM, maPCInfo.mnStrmId ).Save( rStrm );
741 : : // SXVS
742 [ # # ]: 0 : XclExpUInt16Record( EXC_ID_SXVS, EXC_SXVS_SHEET ).Save( rStrm );
743 : :
744 [ # # ]: 0 : if (!maSrcRangeName.isEmpty())
745 : : // DCONNAME
746 : 0 : WriteDConName(rStrm);
747 : : else
748 : : // DCONREF
749 : 0 : WriteDconref(rStrm);
750 : :
751 : : // create the pivot cache storage stream
752 : 0 : WriteCacheStream();
753 : 0 : }
754 : :
755 : 0 : void XclExpPivotCache::SaveXml( XclExpXmlStream&
756 : : #ifdef XLSX_PIVOT_CACHE
757 : : rStrm
758 : : #endif
759 : : )
760 : : {
761 : : OSL_ENSURE( mbValid, "XclExpPivotCache::Save - invalid pivot cache" );
762 : : #ifdef XLSX_PIVOT_CACHE /* <pivotCache> without xl/pivotCaches/ cacheStream
763 : : results in a broken .xlsx */
764 : : sax_fastparser::FSHelperPtr& rWorkbook = rStrm.GetCurrentStream();
765 : : OUString sId = OUStringBuffer()
766 : : .appendAscii("rId")
767 : : .append( rStrm.GetUniqueIdOUString() )
768 : : .makeStringAndClear();
769 : : rWorkbook->startElement( XML_pivotCache,
770 : : XML_cacheId, OString::valueOf( (sal_Int32)maPCInfo.mnStrmId ).getStr(),
771 : : FSNS( XML_r, XML_id ), XclXmlUtils::ToOString( sId ).getStr(),
772 : : FSEND );
773 : : // SXIDSTM
774 : : XclExpUInt16Record( EXC_ID_SXIDSTM, maPCInfo.mnStrmId ).SaveXml( rStrm );
775 : : // SXVS
776 : : XclExpUInt16Record( EXC_ID_SXVS, EXC_SXVS_SHEET ).SaveXml( rStrm );
777 : : // DCONREF
778 : : // OOXTODO: WriteDconref( rStrm );
779 : : // create the pivot cache storage stream
780 : : // OOXTODO: WriteCacheStream();
781 : : rWorkbook->endElement( XML_pivotCache );
782 : : #endif /* XLSX_PIVOT_CACHE */
783 : 0 : }
784 : :
785 : : // private --------------------------------------------------------------------
786 : :
787 : 0 : XclExpPCField* XclExpPivotCache::GetFieldAcc( sal_uInt16 nFieldIdx )
788 : : {
789 : 0 : return maFieldList.GetRecord( nFieldIdx ).get();
790 : : }
791 : :
792 : 0 : XclExpPCField* XclExpPivotCache::GetFieldAcc( const rtl::OUString& rFieldName )
793 : : {
794 : 0 : XclExpPCField* pField = 0;
795 [ # # ][ # # ]: 0 : for( size_t nPos = 0, nSize = maFieldList.GetSize(); !pField && (nPos < nSize); ++nPos )
[ # # ]
796 [ # # ]: 0 : if( maFieldList.GetRecord( nPos )->GetFieldName() == rFieldName )
797 : 0 : pField = maFieldList.GetRecord( nPos ).get();
798 : 0 : return pField;
799 : : }
800 : :
801 : 0 : void XclExpPivotCache::AddFields( const ScDPObject& rDPObj )
802 : : {
803 : 0 : AddStdFields( rDPObj );
804 : 0 : maPCInfo.mnStdFields = GetFieldCount();
805 : 0 : AddGroupFields( rDPObj );
806 : 0 : AddCalcFields( rDPObj );
807 : 0 : maPCInfo.mnTotalFields = GetFieldCount();
808 : 0 : };
809 : :
810 : 0 : void XclExpPivotCache::AddStdFields( const ScDPObject& rDPObj )
811 : : {
812 : : // if item index list is not written, used shortened source range (maDocSrcRange) for performance
813 [ # # ]: 0 : const ScRange& rRange = HasItemIndexList() ? maExpSrcRange : maDocSrcRange;
814 : : // create a standard pivot cache field for each source column
815 [ # # ]: 0 : for( SCCOL nScCol = rRange.aStart.Col(), nEndScCol = rRange.aEnd.Col(); nScCol <= nEndScCol; ++nScCol )
816 : : {
817 : 0 : ScRange aColRange( rRange );
818 : 0 : aColRange.aStart.SetCol( nScCol );
819 : 0 : aColRange.aEnd.SetCol( nScCol );
820 : : maFieldList.AppendNewRecord( new XclExpPCField(
821 [ # # ][ # # ]: 0 : GetRoot(), *this, GetFieldCount(), rDPObj, aColRange ) );
[ # # ][ # # ]
822 : : }
823 : 0 : }
824 : :
825 : 0 : void XclExpPivotCache::AddGroupFields( const ScDPObject& rDPObj )
826 : : {
827 [ # # ]: 0 : if( const ScDPSaveData* pSaveData = rDPObj.GetSaveData() )
828 : : {
829 [ # # ]: 0 : if( const ScDPDimensionSaveData* pSaveDimData = pSaveData->GetExistingDimensionData() )
830 : : {
831 : : // loop over all existing standard fields to find their group fields
832 [ # # ]: 0 : for( sal_uInt16 nFieldIdx = 0; nFieldIdx < maPCInfo.mnStdFields; ++nFieldIdx )
833 : : {
834 [ # # ]: 0 : if( XclExpPCField* pCurrStdField = GetFieldAcc( nFieldIdx ) )
835 : : {
836 : 0 : const ScDPSaveGroupDimension* pGroupDim = pSaveDimData->GetGroupDimForBase( pCurrStdField->GetFieldName() );
837 : 0 : XclExpPCField* pLastGroupField = pCurrStdField;
838 [ # # ]: 0 : while( pGroupDim )
839 : : {
840 : : // insert the new grouping field
841 : : XclExpPCFieldRef xNewGroupField( new XclExpPCField(
842 [ # # ][ # # ]: 0 : GetRoot(), *this, GetFieldCount(), rDPObj, *pGroupDim, *pCurrStdField ) );
[ # # ][ # # ]
843 [ # # ][ # # ]: 0 : maFieldList.AppendRecord( xNewGroupField );
[ # # ]
844 : :
845 : : // register new grouping field at current grouping field, building a chain
846 [ # # ]: 0 : pLastGroupField->SetGroupChildField( *xNewGroupField );
847 : :
848 : : // next grouping dimension
849 [ # # ]: 0 : pGroupDim = pSaveDimData->GetGroupDimForBase( pGroupDim->GetGroupDimName() );
850 : 0 : pLastGroupField = xNewGroupField.get();
851 [ # # ]: 0 : }
852 : : }
853 : : }
854 : : }
855 : : }
856 : 0 : }
857 : :
858 : 0 : void XclExpPivotCache::AddCalcFields( const ScDPObject& /*rDPObj*/ )
859 : : {
860 : : // not supported
861 : 0 : }
862 : :
863 : 0 : void XclExpPivotCache::WriteDconref( XclExpStream& rStrm ) const
864 : : {
865 [ # # ][ # # ]: 0 : XclExpString aRef( XclExpUrlHelper::EncodeUrl( GetRoot(), EMPTY_STRING, &maTabName ) );
[ # # ][ # # ]
866 [ # # ][ # # ]: 0 : rStrm.StartRecord( EXC_ID_DCONREF, 7 + aRef.GetSize() );
867 [ # # ]: 0 : rStrm << static_cast< sal_uInt16 >( maExpSrcRange.aStart.Row() )
868 [ # # ]: 0 : << static_cast< sal_uInt16 >( maExpSrcRange.aEnd.Row() )
869 [ # # ]: 0 : << static_cast< sal_uInt8 >( maExpSrcRange.aStart.Col() )
870 [ # # ]: 0 : << static_cast< sal_uInt8 >( maExpSrcRange.aEnd.Col() )
871 [ # # ]: 0 : << aRef
872 [ # # ]: 0 : << sal_uInt8( 0 );
873 [ # # ]: 0 : rStrm.EndRecord();
874 : 0 : }
875 : :
876 : 0 : void XclExpPivotCache::WriteDConName( XclExpStream& rStrm ) const
877 : : {
878 [ # # ]: 0 : XclExpString aName(maSrcRangeName);
879 [ # # ][ # # ]: 0 : rStrm.StartRecord(EXC_ID_DCONNAME, aName.GetSize() + 2);
880 [ # # ][ # # ]: 0 : rStrm << aName << sal_uInt16(0);
881 [ # # ]: 0 : rStrm.EndRecord();
882 : 0 : }
883 : :
884 : 0 : void XclExpPivotCache::WriteCacheStream()
885 : : {
886 [ # # ][ # # ]: 0 : SotStorageRef xSvStrg = OpenStorage( EXC_STORAGE_PTCACHE );
[ # # ]
887 [ # # ][ # # ]: 0 : SotStorageStreamRef xSvStrm = OpenStream( xSvStrg, ScfTools::GetHexStr( maPCInfo.mnStrmId ) );
[ # # ][ # # ]
888 [ # # ]: 0 : if( xSvStrm.Is() )
889 : : {
890 [ # # ]: 0 : XclExpStream aStrm( *xSvStrm, GetRoot() );
891 : : // SXDB
892 [ # # ]: 0 : WriteSxdb( aStrm );
893 : : // SXDBEX
894 [ # # ]: 0 : WriteSxdbex( aStrm );
895 : : // field list (SXFIELD and items)
896 [ # # ]: 0 : maFieldList.Save( aStrm );
897 : : // index table (list of SXINDEXLIST)
898 [ # # ]: 0 : WriteSxindexlistList( aStrm );
899 : : // EOF
900 [ # # ][ # # ]: 0 : XclExpEmptyRecord( EXC_ID_EOF ).Save( aStrm );
[ # # ][ # # ]
901 [ # # ][ # # ]: 0 : }
902 : 0 : }
903 : :
904 : 0 : void XclExpPivotCache::WriteSxdb( XclExpStream& rStrm ) const
905 : : {
906 : 0 : rStrm.StartRecord( EXC_ID_SXDB, 21 );
907 : 0 : rStrm << maPCInfo;
908 : 0 : rStrm.EndRecord();
909 : 0 : }
910 : :
911 : 0 : void XclExpPivotCache::WriteSxdbex( XclExpStream& rStrm ) const
912 : : {
913 : 0 : rStrm.StartRecord( EXC_ID_SXDBEX, 12 );
914 : 0 : rStrm << EXC_SXDBEX_CREATION_DATE
915 : 0 : << sal_uInt32( 0 ); // number of SXFORMULA records
916 : 0 : rStrm.EndRecord();
917 : 0 : }
918 : :
919 : 0 : void XclExpPivotCache::WriteSxindexlistList( XclExpStream& rStrm ) const
920 : : {
921 [ # # ]: 0 : if( HasItemIndexList() )
922 : : {
923 : 0 : sal_Size nRecSize = 0;
924 : 0 : size_t nPos, nSize = maFieldList.GetSize();
925 [ # # ]: 0 : for( nPos = 0; nPos < nSize; ++nPos )
926 [ # # ]: 0 : nRecSize += maFieldList.GetRecord( nPos )->GetIndexSize();
927 : :
928 [ # # ]: 0 : for( sal_uInt32 nSrcRow = 0; nSrcRow < maPCInfo.mnSrcRecs; ++nSrcRow )
929 : : {
930 : 0 : rStrm.StartRecord( EXC_ID_SXINDEXLIST, nRecSize );
931 [ # # ]: 0 : for( nPos = 0; nPos < nSize; ++nPos )
932 [ # # ]: 0 : maFieldList.GetRecord( nPos )->WriteIndex( rStrm, nSrcRow );
933 : 0 : rStrm.EndRecord();
934 : : }
935 : : }
936 : 0 : }
937 : :
938 : : // ============================================================================
939 : : // Pivot table
940 : : // ============================================================================
941 : :
942 : : namespace {
943 : :
944 : : // ----------------------------------------------------------------------------
945 : :
946 : : /** Returns a display string for a data field containing the field name and aggregation function. */
947 : 0 : String lclGetDataFieldCaption( const String& rFieldName, GeneralFunction eFunc )
948 : : {
949 : 0 : String aCaption;
950 : :
951 : 0 : sal_uInt16 nResIdx = 0;
952 : : using namespace ::com::sun::star::sheet;
953 [ # # # # : 0 : switch( eFunc )
# # # # #
# # # ]
954 : : {
955 : 0 : case GeneralFunction_SUM: nResIdx = STR_FUN_TEXT_SUM; break;
956 : 0 : case GeneralFunction_COUNT: nResIdx = STR_FUN_TEXT_COUNT; break;
957 : 0 : case GeneralFunction_AVERAGE: nResIdx = STR_FUN_TEXT_AVG; break;
958 : 0 : case GeneralFunction_MAX: nResIdx = STR_FUN_TEXT_MAX; break;
959 : 0 : case GeneralFunction_MIN: nResIdx = STR_FUN_TEXT_MIN; break;
960 : 0 : case GeneralFunction_PRODUCT: nResIdx = STR_FUN_TEXT_PRODUCT; break;
961 : 0 : case GeneralFunction_COUNTNUMS: nResIdx = STR_FUN_TEXT_COUNT; break;
962 : 0 : case GeneralFunction_STDEV: nResIdx = STR_FUN_TEXT_STDDEV; break;
963 : 0 : case GeneralFunction_STDEVP: nResIdx = STR_FUN_TEXT_STDDEV; break;
964 : 0 : case GeneralFunction_VAR: nResIdx = STR_FUN_TEXT_VAR; break;
965 : 0 : case GeneralFunction_VARP: nResIdx = STR_FUN_TEXT_VAR; break;
966 : : default:;
967 : : }
968 [ # # ]: 0 : if( nResIdx )
969 [ # # ][ # # ]: 0 : aCaption.Assign( ScGlobal::GetRscString( nResIdx ) ).AppendAscii( RTL_CONSTASCII_STRINGPARAM( " - " ) );
[ # # ]
970 [ # # ]: 0 : aCaption.Append( rFieldName );
971 : 0 : return aCaption;
972 : : }
973 : :
974 : : // ----------------------------------------------------------------------------
975 : :
976 : : } // namespace
977 : :
978 : : // ============================================================================
979 : :
980 : 0 : XclExpPTItem::XclExpPTItem( const XclExpPCField& rCacheField, sal_uInt16 nCacheIdx ) :
981 : : XclExpRecord( EXC_ID_SXVI, 8 ),
982 [ # # ][ # # ]: 0 : mpCacheItem( rCacheField.GetItem( nCacheIdx ) )
983 : : {
984 : 0 : maItemInfo.mnType = EXC_SXVI_TYPE_DATA;
985 : 0 : maItemInfo.mnCacheIdx = nCacheIdx;
986 : 0 : maItemInfo.maVisName.mbUseCache = mpCacheItem != 0;
987 : 0 : }
988 : :
989 : 0 : XclExpPTItem::XclExpPTItem( sal_uInt16 nItemType, sal_uInt16 nCacheIdx, bool bUseCache ) :
990 : : XclExpRecord( EXC_ID_SXVI, 8 ),
991 [ # # ]: 0 : mpCacheItem( 0 )
992 : : {
993 : 0 : maItemInfo.mnType = nItemType;
994 : 0 : maItemInfo.mnCacheIdx = nCacheIdx;
995 : 0 : maItemInfo.maVisName.mbUseCache = bUseCache;
996 : 0 : }
997 : :
998 : 0 : rtl::OUString XclExpPTItem::GetItemName() const
999 : : {
1000 [ # # ]: 0 : return mpCacheItem ? mpCacheItem->ConvertToText() : rtl::OUString();
1001 : : }
1002 : :
1003 : 0 : void XclExpPTItem::SetPropertiesFromMember( const ScDPSaveMember& rSaveMem )
1004 : : {
1005 : : // #i115659# GetIsVisible() is not valid if HasIsVisible() returns false, default is 'visible' then
1006 [ # # ][ # # ]: 0 : ::set_flag( maItemInfo.mnFlags, EXC_SXVI_HIDDEN, rSaveMem.HasIsVisible() && !rSaveMem.GetIsVisible() );
1007 : : // #i115659# GetShowDetails() is not valid if HasShowDetails() returns false, default is 'show detail' then
1008 [ # # ][ # # ]: 0 : ::set_flag( maItemInfo.mnFlags, EXC_SXVI_HIDEDETAIL, rSaveMem.HasShowDetails() && !rSaveMem.GetShowDetails() );
1009 : :
1010 : : // visible name
1011 : 0 : const OUString* pVisName = rSaveMem.GetLayoutName();
1012 [ # # ][ # # ]: 0 : if (pVisName && !pVisName->equals(GetItemName()))
[ # # ][ # # ]
1013 : 0 : maItemInfo.SetVisName(*pVisName);
1014 : 0 : }
1015 : :
1016 : 0 : void XclExpPTItem::WriteBody( XclExpStream& rStrm )
1017 : : {
1018 : 0 : rStrm << maItemInfo;
1019 : 0 : }
1020 : :
1021 : : // ============================================================================
1022 : :
1023 : 0 : XclExpPTField::XclExpPTField( const XclExpPivotTable& rPTable, sal_uInt16 nCacheIdx ) :
1024 : : mrPTable( rPTable ),
1025 [ # # ][ # # ]: 0 : mpCacheField( rPTable.GetCacheField( nCacheIdx ) )
[ # # ][ # # ]
[ # # ][ # # ]
1026 : : {
1027 : 0 : maFieldInfo.mnCacheIdx = nCacheIdx;
1028 : :
1029 : : // create field items
1030 [ # # ]: 0 : if( mpCacheField )
1031 [ # # ][ # # ]: 0 : for( sal_uInt16 nItemIdx = 0, nItemCount = mpCacheField->GetItemCount(); nItemIdx < nItemCount; ++nItemIdx )
1032 [ # # ][ # # ]: 0 : maItemList.AppendNewRecord( new XclExpPTItem( *mpCacheField, nItemIdx ) );
[ # # ]
1033 : 0 : maFieldInfo.mnItemCount = static_cast< sal_uInt16 >( maItemList.GetSize() );
1034 : 0 : }
1035 : :
1036 : : // data access ----------------------------------------------------------------
1037 : :
1038 : 0 : rtl::OUString XclExpPTField::GetFieldName() const
1039 : : {
1040 [ # # ]: 0 : return mpCacheField ? mpCacheField->GetFieldName() : rtl::OUString();
1041 : : }
1042 : :
1043 : 0 : sal_uInt16 XclExpPTField::GetFieldIndex() const
1044 : : {
1045 : : // field index always equal to cache index
1046 : 0 : return maFieldInfo.mnCacheIdx;
1047 : : }
1048 : :
1049 : 0 : sal_uInt16 XclExpPTField::GetLastDataInfoIndex() const
1050 : : {
1051 : : OSL_ENSURE( !maDataInfoVec.empty(), "XclExpPTField::GetLastDataInfoIndex - no data info found" );
1052 : : // will return 0xFFFF for empty vector -> ok
1053 : 0 : return static_cast< sal_uInt16 >( maDataInfoVec.size() - 1 );
1054 : : }
1055 : :
1056 : 0 : sal_uInt16 XclExpPTField::GetItemIndex( const rtl::OUString& rName, sal_uInt16 nDefaultIdx ) const
1057 : : {
1058 [ # # ]: 0 : for( size_t nPos = 0, nSize = maItemList.GetSize(); nPos < nSize; ++nPos )
1059 [ # # ]: 0 : if( maItemList.GetRecord( nPos )->GetItemName() == rName )
1060 : 0 : return static_cast< sal_uInt16 >( nPos );
1061 : 0 : return nDefaultIdx;
1062 : : }
1063 : :
1064 : : // fill data --------------------------------------------------------------
1065 : :
1066 : : /**
1067 : : * Calc's subtotal names are escaped with backslashes ('\'), while Excel's
1068 : : * are not escaped at all.
1069 : : */
1070 : 0 : static OUString lcl_convertCalcSubtotalName(const OUString& rName)
1071 : : {
1072 : 0 : OUStringBuffer aBuf;
1073 : 0 : const sal_Unicode* p = rName.getStr();
1074 : 0 : sal_Int32 n = rName.getLength();
1075 : 0 : bool bEscaped = false;
1076 [ # # ]: 0 : for (sal_Int32 i = 0; i < n; ++i)
1077 : : {
1078 : 0 : const sal_Unicode c = p[i];
1079 [ # # ][ # # ]: 0 : if (!bEscaped && c == sal_Unicode('\\'))
1080 : : {
1081 : 0 : bEscaped = true;
1082 : 0 : continue;
1083 : : }
1084 : :
1085 [ # # ]: 0 : aBuf.append(c);
1086 : 0 : bEscaped = false;
1087 : : }
1088 [ # # ]: 0 : return aBuf.makeStringAndClear();
1089 : : }
1090 : :
1091 : 0 : void XclExpPTField::SetPropertiesFromDim( const ScDPSaveDimension& rSaveDim )
1092 : : {
1093 : : // orientation
1094 : 0 : DataPilotFieldOrientation eOrient = static_cast< DataPilotFieldOrientation >( rSaveDim.GetOrientation() );
1095 : : OSL_ENSURE( eOrient != DataPilotFieldOrientation_DATA, "XclExpPTField::SetPropertiesFromDim - called for data field" );
1096 [ # # ]: 0 : maFieldInfo.AddApiOrient( eOrient );
1097 : :
1098 : : // show empty items (#i115659# GetShowEmpty() is not valid if HasShowEmpty() returns false, default is false then)
1099 [ # # ][ # # ]: 0 : ::set_flag( maFieldExtInfo.mnFlags, EXC_SXVDEX_SHOWALL, rSaveDim.HasShowEmpty() && rSaveDim.GetShowEmpty() );
[ # # ]
1100 : :
1101 : : // visible name
1102 [ # # ]: 0 : const OUString* pLayoutName = rSaveDim.GetLayoutName();
1103 [ # # ][ # # ]: 0 : if (pLayoutName && !pLayoutName->equals(GetFieldName()))
[ # # ][ # # ]
1104 [ # # ]: 0 : maFieldInfo.SetVisName(*pLayoutName);
1105 : :
1106 [ # # ]: 0 : const rtl::OUString* pSubtotalName = rSaveDim.GetSubtotalName();
1107 [ # # ]: 0 : if (pSubtotalName)
1108 : : {
1109 [ # # ]: 0 : OUString aSubName = lcl_convertCalcSubtotalName(*pSubtotalName);
1110 [ # # ][ # # ]: 0 : maFieldExtInfo.mpFieldTotalName.reset(new rtl::OUString(aSubName));
1111 : : }
1112 : :
1113 : : // subtotals
1114 [ # # ]: 0 : XclPTSubtotalVec aSubtotals;
1115 [ # # ]: 0 : aSubtotals.reserve( static_cast< size_t >( rSaveDim.GetSubTotalsCount() ) );
1116 [ # # ]: 0 : for( long nSubtIdx = 0, nSubtCount = rSaveDim.GetSubTotalsCount(); nSubtIdx < nSubtCount; ++nSubtIdx )
1117 [ # # ]: 0 : aSubtotals.push_back( rSaveDim.GetSubTotalFunc( nSubtIdx ) );
1118 [ # # ]: 0 : maFieldInfo.SetSubtotals( aSubtotals );
1119 : :
1120 : : // sorting
1121 [ # # ]: 0 : if( const DataPilotFieldSortInfo* pSortInfo = rSaveDim.GetSortInfo() )
1122 : : {
1123 [ # # ]: 0 : maFieldExtInfo.SetApiSortMode( pSortInfo->Mode );
1124 [ # # ]: 0 : if( pSortInfo->Mode == ::com::sun::star::sheet::DataPilotFieldSortMode::DATA )
1125 [ # # ]: 0 : maFieldExtInfo.mnSortField = mrPTable.GetDataFieldIndex( pSortInfo->Field, EXC_SXVDEX_SORT_OWN );
1126 : 0 : ::set_flag( maFieldExtInfo.mnFlags, EXC_SXVDEX_SORT_ASC, pSortInfo->IsAscending );
1127 : : }
1128 : :
1129 : : // auto show
1130 [ # # ]: 0 : if( const DataPilotFieldAutoShowInfo* pShowInfo = rSaveDim.GetAutoShowInfo() )
1131 : : {
1132 : 0 : ::set_flag( maFieldExtInfo.mnFlags, EXC_SXVDEX_AUTOSHOW, pShowInfo->IsEnabled );
1133 [ # # ]: 0 : maFieldExtInfo.SetApiAutoShowMode( pShowInfo->ShowItemsMode );
1134 [ # # ]: 0 : maFieldExtInfo.SetApiAutoShowCount( pShowInfo->ItemCount );
1135 [ # # ]: 0 : maFieldExtInfo.mnShowField = mrPTable.GetDataFieldIndex( pShowInfo->DataField, EXC_SXVDEX_SHOW_NONE );
1136 : : }
1137 : :
1138 : : // layout
1139 [ # # ]: 0 : if( const DataPilotFieldLayoutInfo* pLayoutInfo = rSaveDim.GetLayoutInfo() )
1140 : : {
1141 [ # # ]: 0 : maFieldExtInfo.SetApiLayoutMode( pLayoutInfo->LayoutMode );
1142 : 0 : ::set_flag( maFieldExtInfo.mnFlags, EXC_SXVDEX_LAYOUT_BLANK, pLayoutInfo->AddEmptyLines );
1143 : : }
1144 : :
1145 : : // special page field properties
1146 [ # # ]: 0 : if( eOrient == DataPilotFieldOrientation_PAGE )
1147 : : {
1148 : 0 : maPageInfo.mnField = GetFieldIndex();
1149 : :
1150 : : // selected item
1151 [ # # ][ # # ]: 0 : if( rSaveDim.HasCurrentPage() )
1152 [ # # ][ # # ]: 0 : maPageInfo.mnSelItem = GetItemIndex( rSaveDim.GetCurrentPage(), EXC_SXPI_ALLITEMS );
1153 : : else
1154 : 0 : maPageInfo.mnSelItem = EXC_SXPI_ALLITEMS;
1155 : : }
1156 : :
1157 : : // item properties
1158 : 0 : const ScDPSaveDimension::MemberList &rMembers = rSaveDim.GetMembers();
1159 [ # # ]: 0 : for (ScDPSaveDimension::MemberList::const_iterator i=rMembers.begin(); i != rMembers.end() ; ++i)
1160 [ # # ][ # # ]: 0 : if( XclExpPTItem* pItem = GetItemAcc( (*i)->GetName() ) )
1161 [ # # ]: 0 : pItem->SetPropertiesFromMember( **i );
1162 : 0 : }
1163 : :
1164 : 0 : void XclExpPTField::SetDataPropertiesFromDim( const ScDPSaveDimension& rSaveDim )
1165 : : {
1166 [ # # ]: 0 : maDataInfoVec.push_back( XclPTDataFieldInfo() );
1167 : 0 : XclPTDataFieldInfo& rDataInfo = maDataInfoVec.back();
1168 : 0 : rDataInfo.mnField = GetFieldIndex();
1169 : :
1170 : : // orientation
1171 : 0 : maFieldInfo.AddApiOrient( DataPilotFieldOrientation_DATA );
1172 : :
1173 : : // aggregation function
1174 : 0 : GeneralFunction eFunc = static_cast< GeneralFunction >( rSaveDim.GetFunction() );
1175 : 0 : rDataInfo.SetApiAggFunc( eFunc );
1176 : :
1177 : : // visible name
1178 : 0 : const rtl::OUString* pVisName = rSaveDim.GetLayoutName();
1179 [ # # ]: 0 : if (pVisName)
1180 : 0 : rDataInfo.SetVisName(*pVisName);
1181 : : else
1182 [ # # ][ # # ]: 0 : rDataInfo.SetVisName( lclGetDataFieldCaption( GetFieldName(), eFunc ) );
[ # # ][ # # ]
[ # # ][ # # ]
1183 : :
1184 : : // result field reference
1185 [ # # ]: 0 : if( const DataPilotFieldReference* pFieldRef = rSaveDim.GetReferenceValue() )
1186 : : {
1187 : 0 : rDataInfo.SetApiRefType( pFieldRef->ReferenceType );
1188 : 0 : rDataInfo.SetApiRefItemType( pFieldRef->ReferenceItemType );
1189 [ # # ]: 0 : if( const XclExpPTField* pRefField = mrPTable.GetField( pFieldRef->ReferenceField ) )
1190 : : {
1191 : 0 : rDataInfo.mnRefField = pRefField->GetFieldIndex();
1192 [ # # ]: 0 : if( pFieldRef->ReferenceItemType == ::com::sun::star::sheet::DataPilotFieldReferenceItemType::NAMED )
1193 : 0 : rDataInfo.mnRefItem = pRefField->GetItemIndex( pFieldRef->ReferenceItemName, 0 );
1194 : : }
1195 : : }
1196 : 0 : }
1197 : :
1198 : 0 : void XclExpPTField::AppendSubtotalItems()
1199 : : {
1200 [ # # ]: 0 : if( maFieldInfo.mnSubtotals & EXC_SXVD_SUBT_DEFAULT ) AppendSubtotalItem( EXC_SXVI_TYPE_DEFAULT );
1201 [ # # ]: 0 : if( maFieldInfo.mnSubtotals & EXC_SXVD_SUBT_SUM ) AppendSubtotalItem( EXC_SXVI_TYPE_SUM );
1202 [ # # ]: 0 : if( maFieldInfo.mnSubtotals & EXC_SXVD_SUBT_COUNT ) AppendSubtotalItem( EXC_SXVI_TYPE_COUNT );
1203 [ # # ]: 0 : if( maFieldInfo.mnSubtotals & EXC_SXVD_SUBT_AVERAGE ) AppendSubtotalItem( EXC_SXVI_TYPE_AVERAGE );
1204 [ # # ]: 0 : if( maFieldInfo.mnSubtotals & EXC_SXVD_SUBT_MAX ) AppendSubtotalItem( EXC_SXVI_TYPE_MAX );
1205 [ # # ]: 0 : if( maFieldInfo.mnSubtotals & EXC_SXVD_SUBT_MIN ) AppendSubtotalItem( EXC_SXVI_TYPE_MIN );
1206 [ # # ]: 0 : if( maFieldInfo.mnSubtotals & EXC_SXVD_SUBT_PROD ) AppendSubtotalItem( EXC_SXVI_TYPE_PROD );
1207 [ # # ]: 0 : if( maFieldInfo.mnSubtotals & EXC_SXVD_SUBT_COUNTNUM ) AppendSubtotalItem( EXC_SXVI_TYPE_COUNTNUM );
1208 [ # # ]: 0 : if( maFieldInfo.mnSubtotals & EXC_SXVD_SUBT_STDDEV ) AppendSubtotalItem( EXC_SXVI_TYPE_STDDEV );
1209 [ # # ]: 0 : if( maFieldInfo.mnSubtotals & EXC_SXVD_SUBT_STDDEVP ) AppendSubtotalItem( EXC_SXVI_TYPE_STDDEVP );
1210 [ # # ]: 0 : if( maFieldInfo.mnSubtotals & EXC_SXVD_SUBT_VAR ) AppendSubtotalItem( EXC_SXVI_TYPE_VAR );
1211 [ # # ]: 0 : if( maFieldInfo.mnSubtotals & EXC_SXVD_SUBT_VARP ) AppendSubtotalItem( EXC_SXVI_TYPE_VARP );
1212 : 0 : }
1213 : :
1214 : : // records --------------------------------------------------------------------
1215 : :
1216 : 0 : void XclExpPTField::WriteSxpiEntry( XclExpStream& rStrm ) const
1217 : : {
1218 : 0 : rStrm << maPageInfo;
1219 : 0 : }
1220 : :
1221 : 0 : void XclExpPTField::WriteSxdi( XclExpStream& rStrm, sal_uInt16 nDataInfoIdx ) const
1222 : : {
1223 : : OSL_ENSURE( nDataInfoIdx < maDataInfoVec.size(), "XclExpPTField::WriteSxdi - data field not found" );
1224 [ # # ]: 0 : if( nDataInfoIdx < maDataInfoVec.size() )
1225 : : {
1226 : 0 : rStrm.StartRecord( EXC_ID_SXDI, 12 );
1227 : 0 : rStrm << maDataInfoVec[ nDataInfoIdx ];
1228 : 0 : rStrm.EndRecord();
1229 : : }
1230 : 0 : }
1231 : :
1232 : 0 : void XclExpPTField::Save( XclExpStream& rStrm )
1233 : : {
1234 : : // SXVD
1235 : 0 : WriteSxvd( rStrm );
1236 : : // list of SXVI records
1237 : 0 : maItemList.Save( rStrm );
1238 : : // SXVDEX
1239 : 0 : WriteSxvdex( rStrm );
1240 : 0 : }
1241 : :
1242 : : // private --------------------------------------------------------------------
1243 : :
1244 : 0 : XclExpPTItem* XclExpPTField::GetItemAcc( const rtl::OUString& rName )
1245 : : {
1246 : 0 : XclExpPTItem* pItem = 0;
1247 [ # # ][ # # ]: 0 : for( size_t nPos = 0, nSize = maItemList.GetSize(); !pItem && (nPos < nSize); ++nPos )
[ # # ]
1248 [ # # ]: 0 : if( maItemList.GetRecord( nPos )->GetItemName() == rName )
1249 : 0 : pItem = maItemList.GetRecord( nPos ).get();
1250 : 0 : return pItem;
1251 : : }
1252 : :
1253 : 0 : void XclExpPTField::AppendSubtotalItem( sal_uInt16 nItemType )
1254 : : {
1255 [ # # ]: 0 : maItemList.AppendNewRecord( new XclExpPTItem( nItemType, EXC_SXVI_DEFAULT_CACHE, true ) );
1256 : 0 : ++maFieldInfo.mnItemCount;
1257 : 0 : }
1258 : :
1259 : 0 : void XclExpPTField::WriteSxvd( XclExpStream& rStrm ) const
1260 : : {
1261 : 0 : rStrm.StartRecord( EXC_ID_SXVD, 10 );
1262 : 0 : rStrm << maFieldInfo;
1263 : 0 : rStrm.EndRecord();
1264 : 0 : }
1265 : :
1266 : 0 : void XclExpPTField::WriteSxvdex( XclExpStream& rStrm ) const
1267 : : {
1268 : 0 : rStrm.StartRecord( EXC_ID_SXVDEX, 20 );
1269 : 0 : rStrm << maFieldExtInfo;
1270 : 0 : rStrm.EndRecord();
1271 : 0 : }
1272 : :
1273 : : // ============================================================================
1274 : :
1275 : 0 : XclExpPivotTable::XclExpPivotTable( const XclExpRoot& rRoot, const ScDPObject& rDPObj, const XclExpPivotCache& rPCache ) :
1276 : : XclExpRoot( rRoot ),
1277 : : mrPCache( rPCache ),
1278 : : maDataOrientField( *this, EXC_SXIVD_DATA ),
1279 : : mnOutScTab( 0 ),
1280 : : mbValid( false ),
1281 [ # # ][ # # ]: 0 : mbFilterBtn( false )
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
1282 : : {
1283 : 0 : const ScRange& rOutScRange = rDPObj.GetOutRange();
1284 [ # # ][ # # ]: 0 : if( GetAddressConverter().ConvertRange( maPTInfo.maOutXclRange, rOutScRange, true ) )
[ # # ]
1285 : : {
1286 : : // DataPilot properties -----------------------------------------------
1287 : :
1288 : : // pivot table properties from DP object
1289 : 0 : mnOutScTab = rOutScRange.aStart.Tab();
1290 : 0 : maPTInfo.maTableName = rDPObj.GetName();
1291 : 0 : maPTInfo.mnCacheIdx = mrPCache.GetCacheIndex();
1292 : :
1293 [ # # ]: 0 : maPTViewEx9Info.Init( rDPObj );
1294 : :
1295 [ # # ]: 0 : if( const ScDPSaveData* pSaveData = rDPObj.GetSaveData() )
1296 : : {
1297 : : // additional properties from ScDPSaveData
1298 [ # # ]: 0 : SetPropertiesFromDP( *pSaveData );
1299 : :
1300 : : // loop over all dimensions ---------------------------------------
1301 : :
1302 : : /* 1) Default-construct all pivot table fields for all pivot cache fields. */
1303 [ # # ][ # # ]: 0 : for( sal_uInt16 nFieldIdx = 0, nFieldCount = mrPCache.GetFieldCount(); nFieldIdx < nFieldCount; ++nFieldIdx )
1304 [ # # ][ # # ]: 0 : maFieldList.AppendNewRecord( new XclExpPTField( *this, nFieldIdx ) );
[ # # ]
1305 : :
1306 [ # # ]: 0 : boost::ptr_vector<ScDPSaveDimension>::const_iterator iter;
1307 [ # # ]: 0 : const ScDPSaveData::DimsType& rDimList = pSaveData->GetDimensions();
1308 : :
1309 : : /* 2) First process all data dimensions, they are needed for extended
1310 : : settings of row/column/page fields (sorting/auto show). */
1311 [ # # ][ # # ]: 0 : for (iter = rDimList.begin(); iter != rDimList.end(); ++iter)
[ # # ][ # # ]
[ # # ]
1312 [ # # ][ # # ]: 0 : if (iter->GetOrientation() == DataPilotFieldOrientation_DATA)
1313 [ # # ][ # # ]: 0 : SetDataFieldPropertiesFromDim(*iter);
1314 : :
1315 : : /* 3) Row/column/page/hidden fields. */
1316 [ # # ][ # # ]: 0 : for (iter = rDimList.begin(); iter != rDimList.end(); ++iter)
[ # # ][ # # ]
[ # # ]
1317 [ # # ][ # # ]: 0 : if (iter->GetOrientation() != DataPilotFieldOrientation_DATA)
1318 [ # # ][ # # ]: 0 : SetFieldPropertiesFromDim(*iter);
1319 : :
1320 : : // Finalize -------------------------------------------------------
1321 : :
1322 [ # # ]: 0 : Finalize();
1323 : 0 : mbValid = true;
1324 : : }
1325 : : }
1326 : 0 : }
1327 : :
1328 : 0 : const XclExpPCField* XclExpPivotTable::GetCacheField( sal_uInt16 nCacheIdx ) const
1329 : : {
1330 : 0 : return mrPCache.GetField( nCacheIdx );
1331 : : }
1332 : :
1333 : 0 : const XclExpPTField* XclExpPivotTable::GetField( sal_uInt16 nFieldIdx ) const
1334 : : {
1335 [ # # ][ # # ]: 0 : return (nFieldIdx == EXC_SXIVD_DATA) ? &maDataOrientField : maFieldList.GetRecord( nFieldIdx ).get();
[ # # ][ # # ]
1336 : : }
1337 : :
1338 : 0 : const XclExpPTField* XclExpPivotTable::GetField( const rtl::OUString& rName ) const
1339 : : {
1340 : 0 : return const_cast< XclExpPivotTable* >( this )->GetFieldAcc( rName );
1341 : : }
1342 : :
1343 : 0 : sal_uInt16 XclExpPivotTable::GetDataFieldIndex( const rtl::OUString& rName, sal_uInt16 nDefaultIdx ) const
1344 : : {
1345 [ # # ][ # # ]: 0 : for( XclPTDataFieldPosVec::const_iterator aIt = maDataFields.begin(), aEnd = maDataFields.end(); aIt != aEnd; ++aIt )
[ # # ]
1346 [ # # ][ # # ]: 0 : if( const XclExpPTField* pField = GetField( aIt->first ) )
[ # # ]
1347 [ # # ]: 0 : if( pField->GetFieldName() == rName )
1348 [ # # ]: 0 : return static_cast< sal_uInt16 >( aIt - maDataFields.begin() );
1349 : 0 : return nDefaultIdx;
1350 : : }
1351 : :
1352 : 0 : void XclExpPivotTable::Save( XclExpStream& rStrm )
1353 : : {
1354 [ # # ]: 0 : if( mbValid )
1355 : : {
1356 : : // SXVIEW
1357 : 0 : WriteSxview( rStrm );
1358 : : // pivot table fields (SXVD, SXVDEX, and item records)
1359 : 0 : maFieldList.Save( rStrm );
1360 : : // SXIVD records for row and column fields
1361 : 0 : WriteSxivd( rStrm, maRowFields );
1362 : 0 : WriteSxivd( rStrm, maColFields );
1363 : : // SXPI
1364 : 0 : WriteSxpi( rStrm );
1365 : : // list of SXDI records containing data field info
1366 : 0 : WriteSxdiList( rStrm );
1367 : : // SXLI records
1368 : 0 : WriteSxli( rStrm, maPTInfo.mnDataRows, maPTInfo.mnRowFields );
1369 : 0 : WriteSxli( rStrm, maPTInfo.mnDataCols, maPTInfo.mnColFields );
1370 : : // SXEX
1371 : 0 : WriteSxex( rStrm );
1372 : : // QSISXTAG
1373 : 0 : WriteQsiSxTag( rStrm );
1374 : : // SXVIEWEX9
1375 : 0 : WriteSxViewEx9( rStrm );
1376 : : }
1377 : 0 : }
1378 : :
1379 : 0 : void XclExpPivotTable::SaveXml( XclExpXmlStream& rStrm )
1380 : : {
1381 [ # # ]: 0 : if( !mbValid )
1382 : 0 : return;
1383 : : sax_fastparser::FSHelperPtr aPivotTableDefinition = rStrm.CreateOutputStream(
1384 : : XclXmlUtils::GetStreamName( "xl/", "pivotTables/pivotTable", mnOutScTab+1),
1385 : : XclXmlUtils::GetStreamName( "../", "pivotTables/pivotTable", mnOutScTab+1),
1386 [ # # ]: 0 : rStrm.GetCurrentStream()->getOutputStream(),
1387 : : "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotTable+xml",
1388 [ # # ][ # # ]: 0 : "http://schemas.openxmlformats.org/officeDocument/2006/relationships/pivotTable");
[ # # ][ # # ]
1389 [ # # ][ # # ]: 0 : rStrm.PushStream( aPivotTableDefinition );
[ # # ]
1390 : :
1391 : : aPivotTableDefinition->startElement( XML_pivotTableDefinition,
1392 : : XML_xmlns, "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
1393 : : XML_name, XclXmlUtils::ToOString( maPTInfo.maTableName ).getStr(),
1394 : : XML_cacheId, OString::valueOf( (sal_Int32) maPTInfo.mnCacheIdx ).getStr(),
1395 : : XML_dataOnRows, XclXmlUtils::ToPsz( maPTInfo.mnDataAxis == EXC_SXVD_AXIS_COL ),
1396 : : XML_dataPosition, OString::valueOf( (sal_Int32) maPTInfo.mnDataPos ).getStr(),
1397 : : XML_autoFormatId, OString::valueOf( (sal_Int32) maPTInfo.mnAutoFmtIdx ).getStr(),
1398 : : // OOXTODO: XML_applyNumberFormats, [ SXVIEW fAtrNum (maPTInfo.mnFlags) ]
1399 : : // OOXTODO: XML_applyBorderFormats, [ SXVIEW fAtrBdr (maPTInfo.mnFlags) ]
1400 : : // OOXTODO: XML_applyFontFormats, [ SXVIEW fAtrFnt (maPTInfo.mnFlags) ]
1401 : : // OOXTODO: XML_applyPatternFormats, [ SXVIEW fAtrPat (maPTInfo.mnFlags) ]
1402 : : // OOXTODO: XML_applyAlignmentFormats, [ SXVIEW fAtrAlc (maPTInfo.mnFlags) ]
1403 : : // OOXTODO: XML_applyWidthHeightFormats, [ SXVIEW fAtrProc (maPTInfo.mnFlags) ]
1404 : : XML_dataCaption, XclXmlUtils::ToOString( maPTInfo.maDataName ).getStr(),
1405 : : // OOXTODO: XML_grandTotalCaption, [ SxViewEx9 chGrand ]
1406 : : // OOXTODO: XML_errorCaption, [ SXEx stError ]
1407 : : // OOXTODO: XML_showError, [ SXEx fDisplayErrorString ]
1408 : : // OOXTODO: XML_missingCaption, [ SXEx stDisplayNull ]
1409 : : // OOXTODO: XML_showMissing, [ SXEx fDisplayNullString ]
1410 : : // OOXTODO: XML_pageStyle, [ SXEx stPageFieldStyle ]
1411 : : // OOXTODO: XML_pivotTableStyle, [ SXEx stTableStyle ]
1412 : : // OOXTODO: XML_vacatedStyle, [ SXEx stVacateStyle ]
1413 : : // OOXTODO: XML_tag, [ SXEx stTag ]
1414 : : // OOXTODO: XML_updatedVersion, [ app-dependent ]
1415 : : // OOXTODO: XML_minRefreshableVersion, [ app-dependent ]
1416 : : // OOXTODO: XML_asteriskTotals, [ QsiSXTag/SXView9Save fHideTotAnnotation ]
1417 : : // OOXTODO: XML_showItems, [ ??? ]
1418 : : // OOXTODO: XML_editData, [ ??? ]
1419 : : // OOXTODO: XML_disableFieldList, [ SXEx fEnableFieldDialog? ]
1420 : : // OOXTODO: XML_showCalcMbrs, [ ??? ]
1421 : : // OOXTODO: XML_visualTotals, [ ??? ]
1422 : : // OOXTODO: XML_showMultipleLabel, [ SXEx fMergeLabels? ]
1423 : : // OOXTODO: XML_showDataDropDown, [ SXEx fEnableDrillDown? ]
1424 : : // OOXTODO: XML_showDrill, [ ??? ]
1425 : : // OOXTODO: XML_printDrill, [ ??? ]
1426 : : // OOXTODO: XML_showMemberPropertyTips,
1427 : : // OOXTODO: XML_showDataTips,
1428 : : // OOXTODO: XML_enableWizard,
1429 : : XML_enableDrill, XclXmlUtils::ToPsz( maPTExtInfo.mnFlags & EXC_SXEX_DRILLDOWN ), // ???
1430 : : // OOXTODO: XML_enableFieldProperties, [ SXEx fEnableFieldDialog (maPTExtInfo.mnFlags) ]
1431 : : // OOXTODO: XML_preserveFormatting, [ SXEx fPreserveFormatting (maPTExtInfo.mnFlags) ]
1432 : : // OOXTODO: XML_pageWrap, [ SXEx cWrapPage (maPTExtInfo.mnFlags) ]
1433 : : // OOXTODO: XML_pageOverThenDown, [ SXEx fAcrossPageLay (maPTExtInfo.mnFlags) ]
1434 : : // OOXTODO: XML_subtotalHiddenItems, [ SXEx fSubtotalHiddenPageItems (maPTExtInfo.mnFlags) ]
1435 : : XML_rowGrandTotals, XclXmlUtils::ToPsz( maPTInfo.mnFlags & EXC_SXVIEW_ROWGRAND ),
1436 : : XML_colGrandTotals, XclXmlUtils::ToPsz( maPTInfo.mnFlags & EXC_SXVIEW_COLGRAND ),
1437 : : // OOXTODO: XML_fieldPrintTitles,
1438 : : // OOXTODO: XML_itemPrintTitles,
1439 : : // OOXTODO: XML_mergeItem,
1440 : : // OOXTODO: XML_showDropZones,
1441 : : // OOXTODO: XML_createdVersion,
1442 : : // OOXTODO: XML_indent,
1443 : : // OOXTODO: XML_showEmptyRow,
1444 : : // OOXTODO: XML_showEmptyCol,
1445 : : // OOXTODO: XML_showHeaders,
1446 : : // OOXTODO: XML_compact,
1447 : : // OOXTODO: XML_outline,
1448 : : // OOXTODO: XML_outlineData,
1449 : : // OOXTODO: XML_compactData,
1450 : : // OOXTODO: XML_published,
1451 : : // OOXTODO: XML_gridDropZones,
1452 : : // OOXTODO: XML_immersive,
1453 : : // OOXTODO: XML_multipleFieldFilters,
1454 : : // OOXTODO: XML_chartFormat,
1455 : : // OOXTODO: XML_rowHeaderCaption,
1456 : : // OOXTODO: XML_colHeaderCaption,
1457 : : // OOXTODO: XML_fieldListSortAscending,
1458 : : // OOXTODO: XML_mdxSubqueries,
1459 : : // OOXTODO: XML_customListSort,
1460 [ # # ][ # # ]: 0 : FSEND );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1461 : :
1462 : : aPivotTableDefinition->singleElement( XML_location,
1463 : : XML_ref, XclXmlUtils::ToOString( maPTInfo.maOutXclRange ).getStr(),
1464 : : XML_firstHeaderRow, OString::valueOf( (sal_Int32) maPTInfo.mnFirstHeadRow ).getStr(),
1465 : : XML_firstDataRow, OString::valueOf( (sal_Int32) maPTInfo.maDataXclPos.mnRow ).getStr(),
1466 : : XML_firstDataCol, OString::valueOf( (sal_Int32) maPTInfo.maDataXclPos.mnCol ).getStr(),
1467 : : XML_rowPageCount, OString::valueOf( (sal_Int32) maPTInfo.mnDataRows ).getStr(), // OOXTODO?
1468 : : XML_colPageCount, OString::valueOf( (sal_Int32) maPTInfo.mnDataCols ).getStr(), // OOXTODO?
1469 [ # # ][ # # ]: 0 : FSEND );
1470 : :
1471 : : // OOXTODO: XML_pivotFields
1472 : :
1473 : : // maPTInfo.mnFields?
1474 [ # # ]: 0 : if( maPTInfo.mnRowFields )
1475 : : {
1476 : : aPivotTableDefinition->startElement( XML_rowFields,
1477 : : XML_count, OString::valueOf( (sal_Int32) maPTInfo.mnRowFields ).getStr(),
1478 [ # # ]: 0 : FSEND );
1479 [ # # ]: 0 : aPivotTableDefinition->endElement( XML_rowFields );
1480 : : }
1481 : :
1482 : : // OOXTODO: XML_rowItems
1483 : :
1484 [ # # ]: 0 : if( maPTInfo.mnColFields )
1485 : : {
1486 : : aPivotTableDefinition->startElement( XML_colFields,
1487 : : XML_count, OString::valueOf( (sal_Int32) maPTInfo.mnColFields ).getStr(),
1488 [ # # ]: 0 : FSEND );
1489 [ # # ]: 0 : aPivotTableDefinition->endElement( XML_colFields );
1490 : : }
1491 : :
1492 : : // OOXTODO: XML_colItems
1493 : :
1494 [ # # ]: 0 : if( maPTInfo.mnPageFields )
1495 : : {
1496 : : aPivotTableDefinition->startElement( XML_pageFields,
1497 : : XML_count, OString::valueOf( (sal_Int32) maPTInfo.mnPageFields ).getStr(),
1498 [ # # ]: 0 : FSEND );
1499 [ # # ]: 0 : aPivotTableDefinition->endElement( XML_pageFields );
1500 : : }
1501 : :
1502 [ # # ]: 0 : if( maPTInfo.mnDataFields )
1503 : : {
1504 : : aPivotTableDefinition->startElement( XML_dataFields,
1505 : : XML_count, OString::valueOf( (sal_Int32) maPTInfo.mnDataFields ).getStr(),
1506 [ # # ]: 0 : FSEND );
1507 [ # # ]: 0 : aPivotTableDefinition->endElement( XML_dataFields );
1508 : : }
1509 : :
1510 : : // OOXTODO: XML_formats, XML_conditionalFormats, XML_chartFormats,
1511 : : // XML_pivotHierarchies, XML_pivotTableStyleInfo, XML_filters,
1512 : : // XML_rowHierarchiesUsage, XML_colHierarchiesUsage, XML_ext
1513 : :
1514 [ # # ]: 0 : aPivotTableDefinition->endElement( XML_pivotTableDefinition );
1515 : :
1516 [ # # ][ # # ]: 0 : rStrm.PopStream();
1517 : : }
1518 : :
1519 : : // private --------------------------------------------------------------------
1520 : :
1521 : 0 : XclExpPTField* XclExpPivotTable::GetFieldAcc( const rtl::OUString& rName )
1522 : : {
1523 : 0 : XclExpPTField* pField = 0;
1524 [ # # ][ # # ]: 0 : for( size_t nPos = 0, nSize = maFieldList.GetSize(); !pField && (nPos < nSize); ++nPos )
[ # # ]
1525 [ # # ]: 0 : if( maFieldList.GetRecord( nPos )->GetFieldName() == rName )
1526 : 0 : pField = maFieldList.GetRecord( nPos ).get();
1527 : 0 : return pField;
1528 : : }
1529 : :
1530 : 0 : XclExpPTField* XclExpPivotTable::GetFieldAcc( const ScDPSaveDimension& rSaveDim )
1531 : : {
1532 : : // data field orientation field?
1533 [ # # ]: 0 : if( rSaveDim.IsDataLayout() )
1534 : 0 : return &maDataOrientField;
1535 : :
1536 : : // a real dimension
1537 [ # # ]: 0 : rtl::OUString aFieldName = ScDPUtil::getSourceDimensionName(rSaveDim.GetName());
1538 [ # # ][ # # ]: 0 : return aFieldName.isEmpty() ? NULL : GetFieldAcc(aFieldName);
1539 : : }
1540 : :
1541 : : // fill data --------------------------------------------------------------
1542 : :
1543 : 0 : void XclExpPivotTable::SetPropertiesFromDP( const ScDPSaveData& rSaveData )
1544 : : {
1545 : 0 : ::set_flag( maPTInfo.mnFlags, EXC_SXVIEW_ROWGRAND, rSaveData.GetRowGrand() );
1546 : 0 : ::set_flag( maPTInfo.mnFlags, EXC_SXVIEW_COLGRAND, rSaveData.GetColumnGrand() );
1547 : 0 : ::set_flag( maPTExtInfo.mnFlags, EXC_SXEX_DRILLDOWN, rSaveData.GetDrillDown() );
1548 : 0 : mbFilterBtn = rSaveData.GetFilterButton();
1549 : 0 : const ScDPSaveDimension* pDim = rSaveData.GetExistingDataLayoutDimension();
1550 [ # # ]: 0 : if (!pDim)
1551 : 0 : return;
1552 : :
1553 : 0 : const rtl::OUString* pLayoutName = pDim->GetLayoutName();
1554 [ # # ]: 0 : if (pLayoutName)
1555 : 0 : maPTInfo.maDataName = *pLayoutName;
1556 : : else
1557 : 0 : maPTInfo.maDataName = ScGlobal::GetRscString(STR_PIVOT_DATA);
1558 : : }
1559 : :
1560 : 0 : void XclExpPivotTable::SetFieldPropertiesFromDim( const ScDPSaveDimension& rSaveDim )
1561 : : {
1562 [ # # ]: 0 : if( XclExpPTField* pField = GetFieldAcc( rSaveDim ) )
1563 : : {
1564 : : // field properties
1565 [ # # ]: 0 : pField->SetPropertiesFromDim( rSaveDim );
1566 : :
1567 : : // update the corresponding field position list
1568 : 0 : DataPilotFieldOrientation eOrient = static_cast< DataPilotFieldOrientation >( rSaveDim.GetOrientation() );
1569 : 0 : sal_uInt16 nFieldIdx = pField->GetFieldIndex();
1570 : 0 : bool bDataLayout = nFieldIdx == EXC_SXIVD_DATA;
1571 : 0 : bool bMultiData = maDataFields.size() > 1;
1572 : :
1573 [ # # ][ # # : 0 : if( !bDataLayout || bMultiData ) switch( eOrient )
# # # ]
[ # # ]
1574 : : {
1575 : : case DataPilotFieldOrientation_ROW:
1576 [ # # ]: 0 : maRowFields.push_back( nFieldIdx );
1577 [ # # ]: 0 : if( bDataLayout )
1578 : 0 : maPTInfo.mnDataAxis = EXC_SXVD_AXIS_ROW;
1579 : 0 : break;
1580 : : case DataPilotFieldOrientation_COLUMN:
1581 [ # # ]: 0 : maColFields.push_back( nFieldIdx );
1582 [ # # ]: 0 : if( bDataLayout )
1583 : 0 : maPTInfo.mnDataAxis = EXC_SXVD_AXIS_COL;
1584 : 0 : break;
1585 : : case DataPilotFieldOrientation_PAGE:
1586 [ # # ]: 0 : maPageFields.push_back( nFieldIdx );
1587 : : OSL_ENSURE( !bDataLayout, "XclExpPivotTable::SetFieldPropertiesFromDim - wrong orientation for data fields" );
1588 : 0 : break;
1589 : : case DataPilotFieldOrientation_DATA:
1590 : : OSL_FAIL( "XclExpPivotTable::SetFieldPropertiesFromDim - called for data field" );
1591 : 0 : break;
1592 : : default:;
1593 : : }
1594 : : }
1595 : 0 : }
1596 : :
1597 : 0 : void XclExpPivotTable::SetDataFieldPropertiesFromDim( const ScDPSaveDimension& rSaveDim )
1598 : : {
1599 [ # # ]: 0 : if( XclExpPTField* pField = GetFieldAcc( rSaveDim ) )
1600 : : {
1601 : : // field properties
1602 : 0 : pField->SetDataPropertiesFromDim( rSaveDim );
1603 : : // update the data field position list
1604 [ # # ][ # # ]: 0 : maDataFields.push_back( XclPTDataFieldPos( pField->GetFieldIndex(), pField->GetLastDataInfoIndex() ) );
1605 : : }
1606 : 0 : }
1607 : :
1608 : 0 : void XclExpPivotTable::Finalize()
1609 : : {
1610 : : // field numbers
1611 : 0 : maPTInfo.mnFields = static_cast< sal_uInt16 >( maFieldList.GetSize() );
1612 : 0 : maPTInfo.mnRowFields = static_cast< sal_uInt16 >( maRowFields.size() );
1613 : 0 : maPTInfo.mnColFields = static_cast< sal_uInt16 >( maColFields.size() );
1614 : 0 : maPTInfo.mnPageFields = static_cast< sal_uInt16 >( maPageFields.size() );
1615 : 0 : maPTInfo.mnDataFields = static_cast< sal_uInt16 >( maDataFields.size() );
1616 : :
1617 : 0 : maPTExtInfo.mnPagePerRow = maPTInfo.mnPageFields;
1618 [ # # ]: 0 : maPTExtInfo.mnPagePerCol = (maPTInfo.mnPageFields > 0) ? 1 : 0;
1619 : :
1620 : : // subtotal items
1621 [ # # ]: 0 : for( size_t nPos = 0, nSize = maFieldList.GetSize(); nPos < nSize; ++nPos )
1622 [ # # ]: 0 : maFieldList.GetRecord( nPos )->AppendSubtotalItems();
1623 : :
1624 : : // find data field orientation field
1625 : 0 : maPTInfo.mnDataPos = EXC_SXVIEW_DATALAST;
1626 : 0 : const ScfUInt16Vec* pFieldVec = 0;
1627 [ # # # ]: 0 : switch( maPTInfo.mnDataAxis )
1628 : : {
1629 : 0 : case EXC_SXVD_AXIS_ROW: pFieldVec = &maRowFields; break;
1630 : 0 : case EXC_SXVD_AXIS_COL: pFieldVec = &maColFields; break;
1631 : : }
1632 : :
1633 [ # # ][ # # ]: 0 : if( pFieldVec && !pFieldVec->empty() && (pFieldVec->back() != EXC_SXIVD_DATA) )
[ # # ][ # # ]
1634 : : {
1635 [ # # ]: 0 : ScfUInt16Vec::const_iterator aIt = ::std::find( pFieldVec->begin(), pFieldVec->end(), EXC_SXIVD_DATA );
1636 [ # # ][ # # ]: 0 : if( aIt != pFieldVec->end() )
1637 [ # # ]: 0 : maPTInfo.mnDataPos = static_cast< sal_uInt16 >( aIt - pFieldVec->begin() );
1638 : : }
1639 : :
1640 : : // single data field is always row oriented
1641 [ # # ]: 0 : if( maPTInfo.mnDataAxis == EXC_SXVD_AXIS_NONE )
1642 : 0 : maPTInfo.mnDataAxis = EXC_SXVD_AXIS_ROW;
1643 : :
1644 : : // update output range (initialized in ctor)
1645 : 0 : sal_uInt16& rnXclCol1 = maPTInfo.maOutXclRange.maFirst.mnCol;
1646 : 0 : sal_uInt32& rnXclRow1 = maPTInfo.maOutXclRange.maFirst.mnRow;
1647 : 0 : sal_uInt16& rnXclCol2 = maPTInfo.maOutXclRange.maLast.mnCol;
1648 : 0 : sal_uInt32& rnXclRow2 = maPTInfo.maOutXclRange.maLast.mnRow;
1649 : : // exclude page fields from output range
1650 : 0 : rnXclRow1 = rnXclRow1 + maPTInfo.mnPageFields;
1651 : : // exclude filter button from output range
1652 [ # # ]: 0 : if( mbFilterBtn )
1653 : 0 : ++rnXclRow1;
1654 : : // exclude empty row between (filter button and/or page fields) and table
1655 [ # # ][ # # ]: 0 : if( mbFilterBtn || maPTInfo.mnPageFields )
1656 : 0 : ++rnXclRow1;
1657 : :
1658 : : // data area
1659 : 0 : sal_uInt16& rnDataXclCol = maPTInfo.maDataXclPos.mnCol;
1660 : 0 : sal_uInt32& rnDataXclRow = maPTInfo.maDataXclPos.mnRow;
1661 : 0 : rnDataXclCol = rnXclCol1 + maPTInfo.mnRowFields;
1662 : 0 : rnDataXclRow = rnXclRow1 + maPTInfo.mnColFields + 1;
1663 [ # # ]: 0 : if( maDataFields.empty() )
1664 : 0 : ++rnDataXclRow;
1665 : :
1666 [ # # ][ # # ]: 0 : bool bExtraHeaderRow = (0 == maPTViewEx9Info.mnGridLayout && maPTInfo.mnColFields == 0);
1667 [ # # ]: 0 : if (bExtraHeaderRow)
1668 : : // Insert an extra row only when there is no column field.
1669 : 0 : ++rnDataXclRow;
1670 : :
1671 : 0 : rnXclCol2 = ::std::max( rnXclCol2, rnDataXclCol );
1672 : 0 : rnXclRow2 = ::std::max( rnXclRow2, rnDataXclRow );
1673 : 0 : maPTInfo.mnDataCols = rnXclCol2 - rnDataXclCol + 1;
1674 : 0 : maPTInfo.mnDataRows = rnXclRow2 - rnDataXclRow + 1;
1675 : :
1676 : : // first heading
1677 : 0 : maPTInfo.mnFirstHeadRow = rnXclRow1;
1678 [ # # ]: 0 : if (bExtraHeaderRow)
1679 : 0 : maPTInfo.mnFirstHeadRow += 2;
1680 : 0 : }
1681 : :
1682 : : // records ----------------------------------------------------------------
1683 : :
1684 : 0 : void XclExpPivotTable::WriteSxview( XclExpStream& rStrm ) const
1685 : : {
1686 : 0 : rStrm.StartRecord( EXC_ID_SXVIEW, 46 + maPTInfo.maTableName.getLength() + maPTInfo.maDataName.getLength() );
1687 : 0 : rStrm << maPTInfo;
1688 : 0 : rStrm.EndRecord();
1689 : 0 : }
1690 : :
1691 : 0 : void XclExpPivotTable::WriteSxivd( XclExpStream& rStrm, const ScfUInt16Vec& rFields ) const
1692 : : {
1693 [ # # ]: 0 : if( !rFields.empty() )
1694 : : {
1695 : 0 : rStrm.StartRecord( EXC_ID_SXIVD, rFields.size() * 2 );
1696 [ # # ][ # # ]: 0 : for( ScfUInt16Vec::const_iterator aIt = rFields.begin(), aEnd = rFields.end(); aIt != aEnd; ++aIt )
[ # # ]
1697 [ # # ][ # # ]: 0 : rStrm << *aIt;
1698 : 0 : rStrm.EndRecord();
1699 : : }
1700 : 0 : }
1701 : :
1702 : 0 : void XclExpPivotTable::WriteSxpi( XclExpStream& rStrm ) const
1703 : : {
1704 [ # # ]: 0 : if( !maPageFields.empty() )
1705 : : {
1706 : 0 : rStrm.StartRecord( EXC_ID_SXPI, maPageFields.size() * 6 );
1707 : 0 : rStrm.SetSliceSize( 6 );
1708 [ # # ][ # # ]: 0 : for( ScfUInt16Vec::const_iterator aIt = maPageFields.begin(), aEnd = maPageFields.end(); aIt != aEnd; ++aIt )
[ # # ]
1709 : : {
1710 [ # # ][ # # ]: 0 : XclExpPTFieldRef xField = maFieldList.GetRecord( *aIt );
1711 [ # # ]: 0 : if( xField )
1712 [ # # ]: 0 : xField->WriteSxpiEntry( rStrm );
1713 [ # # ]: 0 : }
1714 : 0 : rStrm.EndRecord();
1715 : : }
1716 : 0 : }
1717 : :
1718 : 0 : void XclExpPivotTable::WriteSxdiList( XclExpStream& rStrm ) const
1719 : : {
1720 [ # # ][ # # ]: 0 : for( XclPTDataFieldPosVec::const_iterator aIt = maDataFields.begin(), aEnd = maDataFields.end(); aIt != aEnd; ++aIt )
[ # # ]
1721 : : {
1722 [ # # ][ # # ]: 0 : XclExpPTFieldRef xField = maFieldList.GetRecord( aIt->first );
1723 [ # # ]: 0 : if( xField )
1724 [ # # ][ # # ]: 0 : xField->WriteSxdi( rStrm, aIt->second );
1725 [ # # ]: 0 : }
1726 : 0 : }
1727 : :
1728 : 0 : void XclExpPivotTable::WriteSxli( XclExpStream& rStrm, sal_uInt16 nLineCount, sal_uInt16 nIndexCount ) const
1729 : : {
1730 [ # # ]: 0 : if( nLineCount > 0 )
1731 : : {
1732 : 0 : sal_uInt16 nLineSize = 8 + 2 * nIndexCount;
1733 : 0 : rStrm.StartRecord( EXC_ID_SXLI, nLineSize * nLineCount );
1734 : :
1735 : : /* Excel expects the records to be filled completely, do not
1736 : : set a segment size... */
1737 : : // rStrm.SetSliceSize( nLineSize );
1738 : :
1739 [ # # ]: 0 : for( sal_uInt16 nLine = 0; nLine < nLineCount; ++nLine )
1740 : : {
1741 : : // Excel XP needs a partly initialized SXLI record
1742 : 0 : rStrm << sal_uInt16( 0 ) // number of equal index entries
1743 : 0 : << EXC_SXVI_TYPE_DATA
1744 : 0 : << nIndexCount
1745 : 0 : << EXC_SXLI_DEFAULTFLAGS;
1746 : 0 : rStrm.WriteZeroBytes( 2 * nIndexCount );
1747 : : }
1748 : 0 : rStrm.EndRecord();
1749 : : }
1750 : 0 : }
1751 : :
1752 : 0 : void XclExpPivotTable::WriteSxex( XclExpStream& rStrm ) const
1753 : : {
1754 : 0 : rStrm.StartRecord( EXC_ID_SXEX, 24 );
1755 : 0 : rStrm << maPTExtInfo;
1756 : 0 : rStrm.EndRecord();
1757 : 0 : }
1758 : :
1759 : 0 : void XclExpPivotTable::WriteQsiSxTag( XclExpStream& rStrm ) const
1760 : : {
1761 : 0 : rStrm.StartRecord( 0x0802, 32 );
1762 : :
1763 : 0 : sal_uInt16 nRecordType = 0x0802;
1764 : 0 : sal_uInt16 nDummyFlags = 0x0000;
1765 : 0 : sal_uInt16 nTableType = 1; // 0 = query table : 1 = pivot table
1766 : :
1767 : 0 : rStrm << nRecordType << nDummyFlags << nTableType;
1768 : :
1769 : : // General flags
1770 : 0 : bool bEnableRefresh = true;
1771 : 0 : bool bPCacheInvalid = false;
1772 : 0 : bool bOlapPTReport = false;
1773 : :
1774 : 0 : sal_uInt16 nFlags = 0x0000;
1775 [ # # ]: 0 : if (bEnableRefresh) nFlags |= 0x0001;
1776 [ # # ]: 0 : if (bPCacheInvalid) nFlags |= 0x0002;
1777 [ # # ]: 0 : if (bOlapPTReport) nFlags |= 0x0004;
1778 : 0 : rStrm << nFlags;
1779 : :
1780 : : // Feature-specific options. The value differs depending on the table
1781 : : // type, but we assume the table type is always pivot table.
1782 : 0 : sal_uInt32 nOptions = 0x00000000;
1783 : 0 : bool bNoStencil = false;
1784 : 0 : bool bHideTotal = false;
1785 : 0 : bool bEmptyRows = false;
1786 : 0 : bool bEmptyCols = false;
1787 [ # # ]: 0 : if (bNoStencil) nOptions |= 0x00000001;
1788 [ # # ]: 0 : if (bHideTotal) nOptions |= 0x00000002;
1789 [ # # ]: 0 : if (bEmptyRows) nOptions |= 0x00000008;
1790 [ # # ]: 0 : if (bEmptyCols) nOptions |= 0x00000010;
1791 : 0 : rStrm << nOptions;
1792 : :
1793 : : enum ExcelVersion
1794 : : {
1795 : : Excel2000 = 0,
1796 : : ExcelXP = 1,
1797 : : Excel2003 = 2,
1798 : : Excel2007 = 3
1799 : : };
1800 : 0 : ExcelVersion eXclVer = Excel2000;
1801 : 0 : sal_uInt8 nOffsetBytes = 16;
1802 : 0 : rStrm << static_cast<sal_uInt8>(eXclVer) // version table last refreshed
1803 : 0 : << static_cast<sal_uInt8>(eXclVer) // minimum version to refresh
1804 : 0 : << nOffsetBytes
1805 : 0 : << static_cast<sal_uInt8>(eXclVer); // first version created
1806 : :
1807 [ # # ]: 0 : rStrm << XclExpString(maPTInfo.maTableName);
1808 : 0 : rStrm << static_cast<sal_uInt16>(0x0001); // no idea what this is for.
1809 : :
1810 : 0 : rStrm.EndRecord();
1811 : 0 : }
1812 : :
1813 : 0 : void XclExpPivotTable::WriteSxViewEx9( XclExpStream& rStrm ) const
1814 : : {
1815 : : // Until we sync the autoformat ids only export if using grid header layout
1816 : : // That could only have been set via xls import so far.
1817 [ # # ]: 0 : if ( 0 == maPTViewEx9Info.mnGridLayout )
1818 : : {
1819 : 0 : rStrm.StartRecord( EXC_ID_SXVIEWEX9, 17 );
1820 : 0 : rStrm << maPTViewEx9Info;
1821 : 0 : rStrm.EndRecord();
1822 : : }
1823 : 0 : }
1824 : :
1825 : : // ============================================================================
1826 : :
1827 : : namespace {
1828 : :
1829 : : const SCTAB EXC_PTMGR_PIVOTCACHES = SCTAB_MAX;
1830 : :
1831 : : /** Record wrapper class to write the pivot caches or pivot tables. */
1832 [ # # ]: 0 : class XclExpPivotRecWrapper : public XclExpRecordBase
1833 : : {
1834 : : public:
1835 : : explicit XclExpPivotRecWrapper( XclExpPivotTableManager& rPTMgr, SCTAB nScTab );
1836 : : virtual void Save( XclExpStream& rStrm );
1837 : : virtual void SaveXml( XclExpXmlStream& rStrm );
1838 : : private:
1839 : : XclExpPivotTableManager& mrPTMgr;
1840 : : SCTAB mnScTab;
1841 : : };
1842 : :
1843 : 0 : XclExpPivotRecWrapper::XclExpPivotRecWrapper( XclExpPivotTableManager& rPTMgr, SCTAB nScTab ) :
1844 : : mrPTMgr( rPTMgr ),
1845 : 0 : mnScTab( nScTab )
1846 : : {
1847 : 0 : }
1848 : :
1849 : 0 : void XclExpPivotRecWrapper::Save( XclExpStream& rStrm )
1850 : : {
1851 [ # # ]: 0 : if( mnScTab == EXC_PTMGR_PIVOTCACHES )
1852 : 0 : mrPTMgr.WritePivotCaches( rStrm );
1853 : : else
1854 : 0 : mrPTMgr.WritePivotTables( rStrm, mnScTab );
1855 : 0 : }
1856 : :
1857 : 0 : void XclExpPivotRecWrapper::SaveXml( XclExpXmlStream& rStrm )
1858 : : {
1859 [ # # ]: 0 : if( mnScTab == EXC_PTMGR_PIVOTCACHES )
1860 : 0 : mrPTMgr.WritePivotCachesXml( rStrm );
1861 : : else
1862 : 0 : mrPTMgr.WritePivotTablesXml( rStrm, mnScTab );
1863 : 0 : }
1864 : :
1865 : : } // namespace
1866 : :
1867 : : // ----------------------------------------------------------------------------
1868 : :
1869 : 0 : XclExpPivotTableManager::XclExpPivotTableManager( const XclExpRoot& rRoot ) :
1870 : : XclExpRoot( rRoot ),
1871 [ # # ][ # # ]: 0 : mbShareCaches( true )
1872 : : {
1873 : 0 : }
1874 : :
1875 : 0 : void XclExpPivotTableManager::CreatePivotTables()
1876 : : {
1877 [ # # ]: 0 : if( ScDPCollection* pDPColl = GetDoc().GetDPCollection() )
1878 [ # # ]: 0 : for( size_t nDPObj = 0, nCount = pDPColl->GetCount(); nDPObj < nCount; ++nDPObj )
1879 [ # # ]: 0 : if( ScDPObject* pDPObj = (*pDPColl)[ nDPObj ] )
1880 [ # # ]: 0 : if( const XclExpPivotCache* pPCache = CreatePivotCache( *pDPObj ) )
1881 [ # # ]: 0 : maPTableList.AppendNewRecord( new XclExpPivotTable( GetRoot(), *pDPObj, *pPCache ) );
1882 : 0 : }
1883 : :
1884 : 0 : XclExpRecordRef XclExpPivotTableManager::CreatePivotCachesRecord()
1885 : : {
1886 [ # # ]: 0 : return XclExpRecordRef( new XclExpPivotRecWrapper( *this, EXC_PTMGR_PIVOTCACHES ) );
1887 : : }
1888 : :
1889 : 0 : XclExpRecordRef XclExpPivotTableManager::CreatePivotTablesRecord( SCTAB nScTab )
1890 : : {
1891 [ # # ]: 0 : return XclExpRecordRef( new XclExpPivotRecWrapper( *this, nScTab ) );
1892 : : }
1893 : :
1894 : 0 : void XclExpPivotTableManager::WritePivotCaches( XclExpStream& rStrm )
1895 : : {
1896 : 0 : maPCacheList.Save( rStrm );
1897 : 0 : }
1898 : :
1899 : 0 : void XclExpPivotTableManager::WritePivotCachesXml( XclExpXmlStream&
1900 : : #ifdef XLSX_PIVOT_CACHE
1901 : : rStrm
1902 : : #endif
1903 : : )
1904 : : {
1905 : : #ifdef XLSX_PIVOT_CACHE /* <pivotCache> without xl/pivotCaches/ cacheStream
1906 : : results in a broken .xlsx */
1907 : : if( maPCacheList.IsEmpty() )
1908 : : return;
1909 : : sax_fastparser::FSHelperPtr& rWorkbook = rStrm.GetCurrentStream();
1910 : : rWorkbook->startElement( XML_pivotCaches, FSEND );
1911 : : maPCacheList.SaveXml( rStrm );
1912 : : rWorkbook->endElement( XML_pivotCaches );
1913 : : #endif /* XLSX_PIVOT_CACHE */
1914 : 0 : }
1915 : :
1916 : 0 : void XclExpPivotTableManager::WritePivotTables( XclExpStream& rStrm, SCTAB nScTab )
1917 : : {
1918 [ # # ]: 0 : for( size_t nPos = 0, nSize = maPTableList.GetSize(); nPos < nSize; ++nPos )
1919 : : {
1920 [ # # ]: 0 : XclExpPivotTableRef xPTable = maPTableList.GetRecord( nPos );
1921 [ # # ]: 0 : if( xPTable->GetScTab() == nScTab )
1922 [ # # ]: 0 : xPTable->Save( rStrm );
1923 [ # # ]: 0 : }
1924 : 0 : }
1925 : :
1926 : 0 : void XclExpPivotTableManager::WritePivotTablesXml( XclExpXmlStream& rStrm, SCTAB nScTab )
1927 : : {
1928 [ # # ]: 0 : for( size_t nPos = 0, nSize = maPTableList.GetSize(); nPos < nSize; ++nPos )
1929 : : {
1930 [ # # ]: 0 : XclExpPivotTableRef xPTable = maPTableList.GetRecord( nPos );
1931 [ # # ]: 0 : if( xPTable->GetScTab() == nScTab )
1932 [ # # ]: 0 : xPTable->SaveXml( rStrm );
1933 [ # # ]: 0 : }
1934 : 0 : }
1935 : :
1936 : : // private --------------------------------------------------------------------
1937 : :
1938 : 0 : const XclExpPivotCache* XclExpPivotTableManager::CreatePivotCache( const ScDPObject& rDPObj )
1939 : : {
1940 : : // try to find a pivot cache with the same data source
1941 : : /* #i25110# In Excel, the pivot cache contains additional fields
1942 : : (i.e. grouping info, calculated fields). If the passed DataPilot object
1943 : : or the found cache contains this data, do not share the cache with
1944 : : multiple pivot tables. */
1945 [ # # ]: 0 : if( mbShareCaches )
1946 : : {
1947 [ # # ]: 0 : if( const ScDPSaveData* pSaveData = rDPObj.GetSaveData() )
1948 : : {
1949 : 0 : const ScDPDimensionSaveData* pDimSaveData = pSaveData->GetExistingDimensionData();
1950 : : // no dimension save data at all or save data does not contain grouping info
1951 [ # # ][ # # ]: 0 : if( !pDimSaveData || !pDimSaveData->HasGroupDimensions() )
[ # # ][ # # ]
1952 : : {
1953 : : // check all existing pivot caches
1954 [ # # ]: 0 : for( size_t nPos = 0, nSize = maPCacheList.GetSize(); nPos < nSize; ++nPos )
1955 : : {
1956 [ # # ]: 0 : XclExpPivotCacheRef xPCache = maPCacheList.GetRecord( nPos );
1957 : : // pivot cache does not have grouping info and source data is equal
1958 [ # # ][ # # ]: 0 : if( !xPCache->HasAddFields() && xPCache->HasEqualDataSource( rDPObj ) )
[ # # ][ # # ]
1959 : 0 : return xPCache.get();
1960 [ # # ][ # # ]: 0 : }
1961 : : }
1962 : : }
1963 : : }
1964 : :
1965 : : // create a new pivot cache
1966 : 0 : sal_uInt16 nNewCacheIdx = static_cast< sal_uInt16 >( maPCacheList.GetSize() );
1967 [ # # ][ # # ]: 0 : XclExpPivotCacheRef xNewPCache( new XclExpPivotCache( GetRoot(), rDPObj, nNewCacheIdx ) );
[ # # ]
1968 [ # # ]: 0 : if( xNewPCache->IsValid() )
1969 : : {
1970 [ # # ][ # # ]: 0 : maPCacheList.AppendRecord( xNewPCache );
[ # # ]
1971 : 0 : return xNewPCache.get();
1972 : : }
1973 : :
1974 [ # # ]: 0 : return 0;
1975 [ + - ][ + - ]: 24 : }
1976 : :
1977 : : // ============================================================================
1978 : :
1979 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|