1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <pivottablebuffer.hxx>
23 #include <com/sun/star/container/XIndexAccess.hpp>
24 #include <com/sun/star/container/XNameAccess.hpp>
25 #include <com/sun/star/sheet/CellFlags.hpp>
26 #include <com/sun/star/sheet/DataPilotFieldAutoShowInfo.hpp>
27 #include <com/sun/star/sheet/DataPilotFieldLayoutInfo.hpp>
28 #include <com/sun/star/sheet/DataPilotFieldLayoutMode.hpp>
29 #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
30 #include <com/sun/star/sheet/DataPilotFieldReference.hpp>
31 #include <com/sun/star/sheet/DataPilotFieldReferenceItemType.hpp>
32 #include <com/sun/star/sheet/DataPilotFieldReferenceType.hpp>
33 #include <com/sun/star/sheet/DataPilotFieldShowItemsMode.hpp>
34 #include <com/sun/star/sheet/DataPilotFieldSortInfo.hpp>
35 #include <com/sun/star/sheet/DataPilotFieldSortMode.hpp>
36 #include <com/sun/star/sheet/GeneralFunction.hpp>
37 #include <com/sun/star/sheet/XDataPilotDataLayoutFieldSupplier.hpp>
38 #include <com/sun/star/sheet/XDataPilotTablesSupplier.hpp>
39 #include <com/sun/star/sheet/XSheetOperation.hpp>
40 #include <com/sun/star/xml/sax/XFastAttributeList.hpp>
41 #include <osl/diagnose.h>
42 #include <sal/log.hxx>
43 #include <oox/helper/binaryinputstream.hxx>
44 #include <oox/helper/attributelist.hxx>
45 #include <oox/helper/containerhelper.hxx>
46 #include <oox/helper/propertyset.hxx>
47 #include <oox/token/properties.hxx>
48 #include <oox/token/tokens.hxx>
49 #include <addressconverter.hxx>
50 #include <biffhelper.hxx>
52 #include <dapiuno.hxx>
53 #include <dpobject.hxx>
55 #include <dpdimsave.hxx>
56 #include <document.hxx>
57 #include <documentimport.hxx>
58 #include <workbooksettings.hxx>
63 using namespace ::com::sun::star::container
;
64 using namespace ::com::sun::star::sheet
;
65 using namespace ::com::sun::star::table
;
66 using namespace ::com::sun::star::uno
;
70 const sal_Int32 OOX_PT_DATALAYOUTFIELD
= -2; /// Placeholder index of data layout field.
72 const sal_Int32 OOX_PT_PREVIOUS_ITEM
= 0x001000FC; /// Calculation of data item result is based on previous item.
73 const sal_Int32 OOX_PT_NEXT_ITEM
= 0x001000FD; /// Calculation of data item result is based on next item.
75 const sal_uInt32 BIFF12_PTFIELD_DATAFIELD
= 0x00000008;
76 const sal_uInt32 BIFF12_PTFIELD_DEFAULT
= 0x00000100;
77 const sal_uInt32 BIFF12_PTFIELD_SUM
= 0x00000200;
78 const sal_uInt32 BIFF12_PTFIELD_COUNTA
= 0x00000400;
79 const sal_uInt32 BIFF12_PTFIELD_AVERAGE
= 0x00000800;
80 const sal_uInt32 BIFF12_PTFIELD_MAX
= 0x00001000;
81 const sal_uInt32 BIFF12_PTFIELD_MIN
= 0x00002000;
82 const sal_uInt32 BIFF12_PTFIELD_PRODUCT
= 0x00004000;
83 const sal_uInt32 BIFF12_PTFIELD_COUNT
= 0x00008000;
84 const sal_uInt32 BIFF12_PTFIELD_STDDEV
= 0x00010000;
85 const sal_uInt32 BIFF12_PTFIELD_STDDEVP
= 0x00020000;
86 const sal_uInt32 BIFF12_PTFIELD_VAR
= 0x00040000;
87 const sal_uInt32 BIFF12_PTFIELD_VARP
= 0x00080000;
89 const sal_uInt32 BIFF12_PTFIELD_SHOWALL
= 0x00000020;
90 const sal_uInt32 BIFF12_PTFIELD_OUTLINE
= 0x00000040;
91 const sal_uInt32 BIFF12_PTFIELD_INSERTBLANKROW
= 0x00000080;
92 const sal_uInt32 BIFF12_PTFIELD_SUBTOTALTOP
= 0x00000100;
93 const sal_uInt32 BIFF12_PTFIELD_INSERTPAGEBREAK
= 0x00000800;
94 const sal_uInt32 BIFF12_PTFIELD_AUTOSORT
= 0x00001000;
95 const sal_uInt32 BIFF12_PTFIELD_SORTASCENDING
= 0x00002000;
96 const sal_uInt32 BIFF12_PTFIELD_AUTOSHOW
= 0x00004000;
97 const sal_uInt32 BIFF12_PTFIELD_AUTOSHOWTOP
= 0x00008000;
98 const sal_uInt32 BIFF12_PTFIELD_MULTIPAGEITEMS
= 0x00080000;
100 const sal_uInt16 BIFF12_PTFITEM_HIDDEN
= 0x0001;
101 const sal_uInt16 BIFF12_PTFITEM_HIDEDETAILS
= 0x0002;
103 const sal_uInt8 BIFF12_PTPAGEFIELD_HASNAME
= 0x01;
104 const sal_Int32 BIFF12_PTPAGEFIELD_MULTIITEMS
= 0x001000FE;
106 const sal_uInt16 BIFF12_PTFILTER_HASNAME
= 0x0001;
107 const sal_uInt16 BIFF12_PTFILTER_HASDESCRIPTION
= 0x0002;
108 const sal_uInt16 BIFF12_PTFILTER_HASSTRVALUE1
= 0x0004;
109 const sal_uInt16 BIFF12_PTFILTER_HASSTRVALUE2
= 0x0008;
111 const sal_uInt8 BIFF12_TOP10FILTER_TOP
= 0x01;
112 const sal_uInt8 BIFF12_TOP10FILTER_PERCENT
= 0x02;
114 const sal_uInt32 BIFF12_PTDEF_SHOWITEMS
= 0x00000100;
115 const sal_uInt32 BIFF12_PTDEF_DISABLEFIELDLIST
= 0x00000400;
116 const sal_uInt32 BIFF12_PTDEF_HIDECALCMEMBERS
= 0x00001000;
117 const sal_uInt32 BIFF12_PTDEF_WITHHIDDENTOTALS
= 0x00002000;
118 const sal_uInt32 BIFF12_PTDEF_HIDEDRILL
= 0x00100000;
119 const sal_uInt32 BIFF12_PTDEF_PRINTDRILL
= 0x00200000;
120 const sal_uInt32 BIFF12_PTDEF_HIDEHEADERS
= 0x80000000;
122 const sal_uInt32 BIFF12_PTDEF_SHOWEMPTYROW
= 0x00000004;
123 const sal_uInt32 BIFF12_PTDEF_SHOWEMPTYCOL
= 0x00000008;
124 const sal_uInt32 BIFF12_PTDEF_ENABLEDRILL
= 0x00000020;
125 const sal_uInt32 BIFF12_PTDEF_PRESERVEFORMATTING
= 0x00000080;
126 const sal_uInt32 BIFF12_PTDEF_USEAUTOFORMAT
= 0x00000100;
127 const sal_uInt32 BIFF12_PTDEF_SHOWERROR
= 0x00000200;
128 const sal_uInt32 BIFF12_PTDEF_SHOWMISSING
= 0x00000400;
129 const sal_uInt32 BIFF12_PTDEF_PAGEOVERTHENDOWN
= 0x00000800;
130 const sal_uInt32 BIFF12_PTDEF_SUBTOTALHIDDENITEMS
= 0x00001000;
131 const sal_uInt32 BIFF12_PTDEF_ROWGRANDTOTALS
= 0x00002000;
132 const sal_uInt32 BIFF12_PTDEF_COLGRANDTOTALS
= 0x00004000;
133 const sal_uInt32 BIFF12_PTDEF_FIELDPRINTTITLES
= 0x00008000;
134 const sal_uInt32 BIFF12_PTDEF_ITEMPRINTTITLES
= 0x00020000;
135 const sal_uInt32 BIFF12_PTDEF_MERGEITEM
= 0x00040000;
136 const sal_uInt32 BIFF12_PTDEF_HASDATACAPTION
= 0x00080000;
137 const sal_uInt32 BIFF12_PTDEF_HASGRANDTOTALCAPTION
= 0x00100000;
138 const sal_uInt32 BIFF12_PTDEF_HASPAGESTYLE
= 0x00200000;
139 const sal_uInt32 BIFF12_PTDEF_HASPIVOTTABLESTYLE
= 0x00400000;
140 const sal_uInt32 BIFF12_PTDEF_HASVACATEDSTYLE
= 0x00800000;
141 const sal_uInt32 BIFF12_PTDEF_APPLYNUMFMT
= 0x01000000;
142 const sal_uInt32 BIFF12_PTDEF_APPLYFONT
= 0x02000000;
143 const sal_uInt32 BIFF12_PTDEF_APPLYALIGNMENT
= 0x04000000;
144 const sal_uInt32 BIFF12_PTDEF_APPLYBORDER
= 0x08000000;
145 const sal_uInt32 BIFF12_PTDEF_APPLYFILL
= 0x10000000;
146 const sal_uInt32 BIFF12_PTDEF_APPLYPROTECTION
= 0x20000000;
147 const sal_uInt32 BIFF12_PTDEF_HASTAG
= 0x40000000;
149 const sal_uInt32 BIFF12_PTDEF_NOERRORCAPTION
= 0x00000040;
150 const sal_uInt32 BIFF12_PTDEF_NOMISSINGCAPTION
= 0x00000080;
151 const sal_uInt32 BIFF12_PTDEF_HASROWHEADERCAPTION
= 0x00000400;
152 const sal_uInt32 BIFF12_PTDEF_HASCOLHEADERCAPTION
= 0x00000800;
153 const sal_uInt32 BIFF12_PTDEF_FIELDLISTSORTASC
= 0x00001000;
154 const sal_uInt32 BIFF12_PTDEF_NOCUSTOMLISTSORT
= 0x00004000;
156 const sal_uInt8 BIFF12_PTDEF_ROWAXIS
= 1;
157 const sal_uInt8 BIFF12_PTDEF_COLAXIS
= 2;
161 PTFieldItemModel::PTFieldItemModel() :
164 mbShowDetails( true ),
169 void PTFieldItemModel::setBiffType( sal_uInt16 nType
)
171 static const sal_Int32 spnTypes
[] = { XML_data
, XML_default
,
172 XML_sum
, XML_countA
, XML_avg
, XML_max
, XML_min
, XML_product
, XML_count
,
173 XML_stdDev
, XML_stdDevP
, XML_var
, XML_varP
, XML_grand
, XML_blank
};
174 mnType
= STATIC_ARRAY_SELECT( spnTypes
, nType
, XML_data
);
177 PTFieldModel::PTFieldModel() :
178 mnAxis( XML_TOKEN_INVALID
),
180 mnAutoShowItems( 10 ),
181 mnAutoShowRankBy( -1 ),
182 mnSortType( XML_manual
),
183 mnSortRefField( -1 ),
185 mbDataField( false ),
186 mbDefaultSubtotal( true ),
187 mbSumSubtotal( false ),
188 mbCountASubtotal( false ),
189 mbAverageSubtotal( false ),
190 mbMaxSubtotal( false ),
191 mbMinSubtotal( false ),
192 mbProductSubtotal( false ),
193 mbCountSubtotal( false ),
194 mbStdDevSubtotal( false ),
195 mbStdDevPSubtotal( false ),
196 mbVarSubtotal( false ),
197 mbVarPSubtotal( false ),
200 mbSubtotalTop( true ),
201 mbInsertBlankRow( false ),
202 mbInsertPageBreak( false ),
204 mbTopAutoShow( true ),
205 mbMultiPageItems( false )
209 void PTFieldModel::setBiffAxis( sal_uInt8 nAxis
)
211 /* Weird. The axis field is organized as bit field, but only one of the
212 row/col/page flags are allowed at the same time and refer to the values
213 'axisRow', 'axisCol', and 'axisPage' of the XML attribute
214 'pivotField@axis'. Additionally, the fourth bit determines if the field
215 is a data field, which may appear combined with the row/col/page flags.
216 Therefore, this bit is unrelated to the 'axisValues' value of the
217 'pivotField@axis' attribute, but refers to the 'pivotField@dataField'
218 boolean attribute. */
219 static const sal_Int32 spnAxisIds
[] = { XML_TOKEN_INVALID
, XML_axisRow
, XML_axisCol
, XML_TOKEN_INVALID
, XML_axisPage
};
220 mnAxis
= STATIC_ARRAY_SELECT( spnAxisIds
, nAxis
, XML_TOKEN_INVALID
);
223 PTPageFieldModel::PTPageFieldModel() :
225 mnItem( BIFF12_PTPAGEFIELD_MULTIITEMS
)
229 PTDataFieldModel::PTDataFieldModel() :
231 mnSubtotal( XML_sum
),
232 mnShowDataAs( XML_normal
),
239 void PTDataFieldModel::setBiffSubtotal( sal_Int32 nSubtotal
)
241 static const sal_Int32 spnSubtotals
[] = { XML_sum
, XML_count
, XML_average
, XML_max
, XML_min
, XML_product
, XML_countNums
, XML_stdDev
, XML_stdDevp
, XML_var
, XML_varp
};
242 mnSubtotal
= STATIC_ARRAY_SELECT( spnSubtotals
, nSubtotal
, XML_TOKEN_INVALID
);
245 void PTDataFieldModel::setBiffShowDataAs( sal_Int32 nShowDataAs
)
247 static const sal_Int32 spnShowDataAs
[] = { XML_normal
, XML_difference
, XML_percent
, XML_percentDiff
, XML_runTotal
, XML_percentOfRow
, XML_percentOfCol
, XML_percentOfTotal
, XML_index
};
248 mnShowDataAs
= STATIC_ARRAY_SELECT( spnShowDataAs
, nShowDataAs
, XML_TOKEN_INVALID
);
251 PivotTableField::PivotTableField( PivotTable
& rPivotTable
, sal_Int32 nFieldIndex
) :
252 WorkbookHelper( rPivotTable
),
253 mrPivotTable( rPivotTable
),
254 mnFieldIndex( nFieldIndex
)
258 void PivotTableField::importPivotField( const AttributeList
& rAttribs
)
260 /* The documentation mentions a value 'axisValues' for the attribute
261 'pivotField@axis'. But this value is not used to mark a data field, as
262 data fields may be inserted in one of the row/column/page dimensions at
263 the same time. Therefore, the boolean attribute 'pivotField@dataField'
264 is really used to mark data fields. */
265 maModel
.mnAxis
= rAttribs
.getToken( XML_axis
, XML_TOKEN_INVALID
);
266 maModel
.mnNumFmtId
= rAttribs
.getInteger( XML_numFmtId
, 0 );
267 maModel
.mnAutoShowItems
= rAttribs
.getInteger( XML_itemPageCount
, 10 );
268 maModel
.mnAutoShowRankBy
= rAttribs
.getInteger( XML_rankBy
, -1 );
269 maModel
.mnSortType
= rAttribs
.getToken( XML_sortType
, XML_manual
);
270 maModel
.mbDataField
= rAttribs
.getBool( XML_dataField
, false );
271 maModel
.mbDefaultSubtotal
= rAttribs
.getBool( XML_defaultSubtotal
, true );
272 maModel
.mbSumSubtotal
= rAttribs
.getBool( XML_sumSubtotal
, false );
273 maModel
.mbCountASubtotal
= rAttribs
.getBool( XML_countASubtotal
, false );
274 maModel
.mbAverageSubtotal
= rAttribs
.getBool( XML_avgSubtotal
, false );
275 maModel
.mbMaxSubtotal
= rAttribs
.getBool( XML_maxSubtotal
, false );
276 maModel
.mbMinSubtotal
= rAttribs
.getBool( XML_minSubtotal
, false );
277 maModel
.mbProductSubtotal
= rAttribs
.getBool( XML_productSubtotal
, false );
278 maModel
.mbCountSubtotal
= rAttribs
.getBool( XML_countSubtotal
, false );
279 maModel
.mbStdDevSubtotal
= rAttribs
.getBool( XML_stdDevSubtotal
, false );
280 maModel
.mbStdDevPSubtotal
= rAttribs
.getBool( XML_stdDevPSubtotal
, false );
281 maModel
.mbVarSubtotal
= rAttribs
.getBool( XML_varSubtotal
, false );
282 maModel
.mbVarPSubtotal
= rAttribs
.getBool( XML_varPSubtotal
, false );
283 maModel
.mbShowAll
= rAttribs
.getBool( XML_showAll
, true );
284 maModel
.mbOutline
= rAttribs
.getBool( XML_outline
, true );
285 maModel
.mbSubtotalTop
= rAttribs
.getBool( XML_subtotalTop
, true );
286 maModel
.mbInsertBlankRow
= rAttribs
.getBool( XML_insertBlankRow
, false );
287 maModel
.mbInsertPageBreak
= rAttribs
.getBool( XML_insertPageBreak
, false );
288 maModel
.mbAutoShow
= rAttribs
.getBool( XML_autoShow
, false );
289 maModel
.mbTopAutoShow
= rAttribs
.getBool( XML_topAutoShow
, true );
290 maModel
.mbMultiPageItems
= rAttribs
.getBool( XML_multipleItemSelectionAllowed
, false );
293 void PivotTableField::importItem( const AttributeList
& rAttribs
)
295 PTFieldItemModel aModel
;
296 aModel
.mnCacheItem
= rAttribs
.getInteger( XML_x
, -1 );
297 aModel
.mnType
= rAttribs
.getToken( XML_t
, XML_data
);
298 aModel
.mbShowDetails
= rAttribs
.getBool( XML_sd
, true );
299 aModel
.mbHidden
= rAttribs
.getBool( XML_h
, false );
300 aModel
.msCaption
= rAttribs
.getXString( XML_n
, OUString() );
301 maItems
.push_back( aModel
);
304 void PivotTableField::importReference( const AttributeList
& rAttribs
)
306 // field index is stored as unsigned integer
307 maModel
.mnSortRefField
= static_cast< sal_Int32
>( rAttribs
.getUnsigned( XML_field
, SAL_MAX_UINT32
) );
310 void PivotTableField::importReferenceItem( const AttributeList
& rAttribs
)
312 maModel
.mnSortRefItem
= rAttribs
.getInteger( XML_v
, -1 );
315 void PivotTableField::importPTField( SequenceInputStream
& rStrm
)
317 sal_uInt32 nFlags1
, nFlags2
;
318 nFlags1
= rStrm
.readuInt32();
319 maModel
.mnNumFmtId
= rStrm
.readInt32();
320 nFlags2
= rStrm
.readuInt32();
321 maModel
.mnAutoShowItems
= rStrm
.readInt32();
322 maModel
.mnAutoShowRankBy
= rStrm
.readInt32();
324 maModel
.setBiffAxis( extractValue
< sal_uInt8
>( nFlags1
, 0, 3 ) );
325 maModel
.mbDataField
= getFlag( nFlags1
, BIFF12_PTFIELD_DATAFIELD
);
326 maModel
.mbDefaultSubtotal
= getFlag( nFlags1
, BIFF12_PTFIELD_DEFAULT
);
327 maModel
.mbSumSubtotal
= getFlag( nFlags1
, BIFF12_PTFIELD_SUM
);
328 maModel
.mbCountASubtotal
= getFlag( nFlags1
, BIFF12_PTFIELD_COUNTA
);
329 maModel
.mbAverageSubtotal
= getFlag( nFlags1
, BIFF12_PTFIELD_AVERAGE
);
330 maModel
.mbMaxSubtotal
= getFlag( nFlags1
, BIFF12_PTFIELD_MAX
);
331 maModel
.mbMinSubtotal
= getFlag( nFlags1
, BIFF12_PTFIELD_MIN
);
332 maModel
.mbProductSubtotal
= getFlag( nFlags1
, BIFF12_PTFIELD_PRODUCT
);
333 maModel
.mbCountSubtotal
= getFlag( nFlags1
, BIFF12_PTFIELD_COUNT
);
334 maModel
.mbStdDevSubtotal
= getFlag( nFlags1
, BIFF12_PTFIELD_STDDEV
);
335 maModel
.mbStdDevPSubtotal
= getFlag( nFlags1
, BIFF12_PTFIELD_STDDEVP
);
336 maModel
.mbVarSubtotal
= getFlag( nFlags1
, BIFF12_PTFIELD_VAR
);
337 maModel
.mbVarPSubtotal
= getFlag( nFlags1
, BIFF12_PTFIELD_VARP
);
339 maModel
.mbShowAll
= getFlag( nFlags2
, BIFF12_PTFIELD_SHOWALL
);
340 maModel
.mbOutline
= getFlag( nFlags2
, BIFF12_PTFIELD_OUTLINE
);
341 maModel
.mbSubtotalTop
= getFlag( nFlags2
, BIFF12_PTFIELD_SUBTOTALTOP
);
342 maModel
.mbInsertBlankRow
= getFlag( nFlags2
, BIFF12_PTFIELD_INSERTBLANKROW
);
343 maModel
.mbInsertPageBreak
= getFlag( nFlags2
, BIFF12_PTFIELD_INSERTPAGEBREAK
);
344 maModel
.mbAutoShow
= getFlag( nFlags2
, BIFF12_PTFIELD_AUTOSHOW
);
345 maModel
.mbTopAutoShow
= getFlag( nFlags2
, BIFF12_PTFIELD_AUTOSHOWTOP
);
346 maModel
.mbMultiPageItems
= getFlag( nFlags2
, BIFF12_PTFIELD_MULTIPAGEITEMS
);
348 bool bAutoSort
= getFlag( nFlags2
, BIFF12_PTFIELD_AUTOSORT
);
349 bool bAscending
= getFlag( nFlags2
, BIFF12_PTFIELD_SORTASCENDING
);
350 maModel
.mnSortType
= bAutoSort
? (bAscending
? XML_ascending
: XML_descending
) : XML_manual
;
353 void PivotTableField::importPTFItem( SequenceInputStream
& rStrm
)
355 PTFieldItemModel aModel
;
358 nType
= rStrm
.readuChar();
359 nFlags
= rStrm
.readuInt16();
360 aModel
.mnCacheItem
= rStrm
.readInt32();
362 aModel
.setBiffType( nType
);
363 aModel
.mbShowDetails
= !getFlag( nFlags
, BIFF12_PTFITEM_HIDEDETAILS
);
364 aModel
.mbHidden
= getFlag( nFlags
, BIFF12_PTFITEM_HIDDEN
);
366 maItems
.push_back( aModel
);
369 void PivotTableField::importPTReference( SequenceInputStream
& rStrm
)
371 maModel
.mnSortRefField
= rStrm
.readInt32();
374 void PivotTableField::importPTReferenceItem( SequenceInputStream
& rStrm
)
376 maModel
.mnSortRefItem
= rStrm
.readInt32();
379 void PivotTableField::finalizeImport( const Reference
< XDataPilotDescriptor
>& rxDPDesc
)
381 /* Process all fields based on source data, other fields (e.g. group
382 fields) are processed from here. PivotCacahe::getDatabaseIndex()
383 returns -1 for all fields not based on source data. */
384 Reference
< XDataPilotField
> xDPField
;
385 sal_Int32 nDatabaseIdx
= mrPivotTable
.getCacheDatabaseIndex( mnFieldIndex
);
386 if( (nDatabaseIdx
>= 0) && rxDPDesc
.is() ) try
388 // try to get the source field and its name from passed DataPilot descriptor
389 Reference
< XIndexAccess
> xDPFieldsIA( rxDPDesc
->getDataPilotFields(), UNO_SET_THROW
);
390 xDPField
.set( xDPFieldsIA
->getByIndex( nDatabaseIdx
), UNO_QUERY_THROW
);
391 Reference
< XNamed
> xDPFieldName( xDPField
, UNO_QUERY_THROW
);
392 maDPFieldName
= xDPFieldName
->getName();
393 OSL_ENSURE( !maDPFieldName
.isEmpty(), "PivotTableField::finalizeImport - no field name in source data found" );
395 // try to convert grouping settings
396 if( const PivotCacheField
* pCacheField
= mrPivotTable
.getCacheField( mnFieldIndex
) )
398 // numeric grouping is done inplace, no nested group fields will appear
399 if( pCacheField
->hasNumericGrouping() )
401 pCacheField
->convertNumericGrouping( xDPField
);
403 else if( pCacheField
->hasDateGrouping() )
405 // first date group settings are inplace
406 pCacheField
->createDateGroupField( xDPField
);
407 // create all nested group fields (if any)
408 mrPivotTable
.finalizeDateGroupingImport( xDPField
, mnFieldIndex
);
410 else if( pCacheField
->hasParentGrouping() )
413 // create a list of all item names, needed to map between original and group items
414 ::std::vector
< OUString
> aItems
;
415 pCacheField
->getCacheItemNames( aItems
);
416 PivotCacheGroupItemVector aItemNames
;
417 for( const auto& rItem
: aItems
)
418 aItemNames
.emplace_back( rItem
);
419 // create all nested group fields (if any)
420 mrPivotTable
.finalizeParentGroupingImport( xDPField
, *pCacheField
, aItemNames
);
429 void PivotTableField::finalizeDateGroupingImport( const Reference
< XDataPilotField
>& rxBaseDPField
, sal_Int32 nBaseFieldIdx
)
431 if( maDPFieldName
.isEmpty() ) // prevent endless loops if file format is broken
433 if( PivotCacheField
* pCacheField
= mrPivotTable
.getCacheField( mnFieldIndex
) )
435 if( !pCacheField
->isDatabaseField() && pCacheField
->hasDateGrouping() && (pCacheField
->getGroupBaseField() == nBaseFieldIdx
) )
437 maDPFieldName
= pCacheField
->createDateGroupField( rxBaseDPField
);
438 pCacheField
->setFinalGroupName(maDPFieldName
);
439 OSL_ENSURE( !maDPFieldName
.isEmpty(), "PivotTableField::finalizeDateGroupingImport - cannot create date group field" );
445 void PivotTableField::finalizeParentGroupingImport( const Reference
< XDataPilotField
>& rxBaseDPField
, const PivotCacheField
& rBaseCacheField
, PivotCacheGroupItemVector
& orItemNames
)
447 if( maDPFieldName
.isEmpty() ) // prevent endless loops if file format is broken
449 if( PivotCacheField
* pCacheField
= mrPivotTable
.getCacheField( mnFieldIndex
) )
451 // data field can have user defined groupname captions, apply them
453 IdCaptionPairList captionList
;
454 for( const auto& rItem
: maItems
)
456 if ( rItem
.mnType
== XML_data
&& rItem
.msCaption
.getLength() )
457 captionList
.emplace_back( rItem
.mnCacheItem
, rItem
.msCaption
);
459 if ( !captionList
.empty() )
460 pCacheField
->applyItemCaptions( captionList
);
462 maDPFieldName
= pCacheField
->createParentGroupField( rxBaseDPField
, rBaseCacheField
, orItemNames
);
463 pCacheField
->setFinalGroupName(maDPFieldName
);
464 // on success, try to create nested group fields
465 Reference
< XDataPilotField
> xDPField
= mrPivotTable
.getDataPilotField( maDPFieldName
);
467 mrPivotTable
.finalizeParentGroupingImport( xDPField
, *pCacheField
, orItemNames
);
472 void PivotTableField::finalizeImportBasedOnCache( const Reference
< XDataPilotDescriptor
>& rxDPDesc
)
474 /* Process all fields based on source data, other fields (e.g. group
475 fields) are processed based on cache fields.*/
476 Reference
< XDataPilotField
> xDPField
;
477 sal_Int32 nDatabaseIdx
= mrPivotTable
.getCacheDatabaseIndex( mnFieldIndex
);
478 if( (nDatabaseIdx
>= 0) && rxDPDesc
.is() ) try
480 // Try to get the source field and its name from passed DataPilot descriptor
481 Reference
< XIndexAccess
> xDPFieldsIA( rxDPDesc
->getDataPilotFields(), UNO_SET_THROW
);
482 xDPField
.set( xDPFieldsIA
->getByIndex( nDatabaseIdx
), UNO_QUERY_THROW
);
483 Reference
< XNamed
> xDPFieldName( xDPField
, UNO_QUERY_THROW
);
484 maDPFieldName
= xDPFieldName
->getName();
485 SAL_WARN_IF( maDPFieldName
.isEmpty(), "sc.filter", "PivotTableField::finalizeImportBasedOnCache - no field name in source data found" );
491 // Use group names already generated for another table using the same group field.
492 if( const PivotCacheField
* pCacheField
= mrPivotTable
.getCacheField( mnFieldIndex
) )
494 if(!pCacheField
->getFinalGroupName().isEmpty())
495 maDPFieldName
= pCacheField
->getFinalGroupName();
499 void PivotTableField::convertRowField()
501 convertRowColPageField( XML_axisRow
);
504 void PivotTableField::convertColField()
506 convertRowColPageField( XML_axisCol
);
509 void PivotTableField::convertHiddenField()
511 convertRowColPageField( XML_TOKEN_INVALID
);
514 void PivotTableField::convertPageField( const PTPageFieldModel
& rPageField
)
516 OSL_ENSURE( rPageField
.mnField
== mnFieldIndex
, "PivotTableField::convertPageField - wrong field index" );
517 // convert all settings common for row/column/page fields
518 Reference
< XDataPilotField
> xDPField
= convertRowColPageField( XML_axisPage
);
522 PropertySet
aPropSet( xDPField
);
524 // find cache item used as 'selected page'
525 sal_Int32 nCacheItem
= -1;
526 if( maModel
.mbMultiPageItems
)
528 // multiple items may be selected
529 OSL_ENSURE( rPageField
.mnItem
== BIFF12_PTPAGEFIELD_MULTIITEMS
, "PivotTableField::convertPageField - unexpected cache item index" );
530 // try to find a single visible item
531 bool bHasMultiItems
= false;
532 for( const auto& rItem
: maItems
)
534 if( (rItem
.mnType
== XML_data
) && !rItem
.mbHidden
)
536 bHasMultiItems
= nCacheItem
>= 0;
537 nCacheItem
= bHasMultiItems
? -1 : rItem
.mnCacheItem
;
546 // single item may be selected
547 if( (0 <= rPageField
.mnItem
) && (rPageField
.mnItem
< static_cast< sal_Int32
>( maItems
.size() )) )
548 nCacheItem
= maItems
[ rPageField
.mnItem
].mnCacheItem
;
551 if( nCacheItem
>= 0 )
553 if( const PivotCacheField
* pCacheField
= mrPivotTable
.getCacheField( mnFieldIndex
) )
555 if( const PivotCacheItem
* pSharedItem
= pCacheField
->getCacheItem( nCacheItem
) )
557 ScDPObject
* pDPObj
= mrPivotTable
.getDPObject();
558 ScDPSaveData
* pSaveData
= pDPObj
->GetSaveData();
559 ScDPSaveDimension
* pDim
= pSaveData
->GetDimensionByName(pCacheField
->getName());
560 OUString aSelectedPage
= pSharedItem
->getFormattedName(*pDim
, pDPObj
, DateTime(getWorkbookSettings().getNullDate()));
561 aPropSet
.setProperty( PROP_SelectedPage
, aSelectedPage
);
568 void PivotTableField::convertDataField( const PTDataFieldModel
& rDataField
)
570 OSL_ENSURE( rDataField
.mnField
== mnFieldIndex
, "PivotTableField::convertDataField - wrong field index" );
571 OSL_ENSURE( maModel
.mbDataField
, "PivotTableField::convertDataField - not a data field" );
572 Reference
< XDataPilotField
> xDPField
= mrPivotTable
.getDataPilotField( maDPFieldName
);
575 PropertySet
aPropSet( xDPField
);
578 aPropSet
.setProperty( PROP_Orientation
, DataPilotFieldOrientation_DATA
);
580 if (!rDataField
.maName
.isEmpty())
581 aPropSet
.setProperty(PROP_Name
, rDataField
.maName
);
583 /* Field aggregation function. Documentation is a little bit confused
584 about which names to use for the count functions. The name 'count'
585 means 'count all', and 'countNum' means 'count numbers'. On the
586 other hand, for subtotals, 'countA' means 'count all', and 'count'
587 means 'count numbers' (see above). */
588 GeneralFunction eAggFunc
= GeneralFunction_SUM
;
589 switch( rDataField
.mnSubtotal
)
591 case XML_sum
: eAggFunc
= GeneralFunction_SUM
; break;
592 case XML_count
: eAggFunc
= GeneralFunction_COUNT
; break;
593 case XML_average
: eAggFunc
= GeneralFunction_AVERAGE
; break;
594 case XML_max
: eAggFunc
= GeneralFunction_MAX
; break;
595 case XML_min
: eAggFunc
= GeneralFunction_MIN
; break;
596 case XML_product
: eAggFunc
= GeneralFunction_PRODUCT
; break;
597 case XML_countNums
: eAggFunc
= GeneralFunction_COUNTNUMS
; break;
598 case XML_stdDev
: eAggFunc
= GeneralFunction_STDEV
; break;
599 case XML_stdDevp
: eAggFunc
= GeneralFunction_STDEVP
; break;
600 case XML_var
: eAggFunc
= GeneralFunction_VAR
; break;
601 case XML_varp
: eAggFunc
= GeneralFunction_VARP
; break;
602 default: OSL_FAIL( "PivotTableField::convertDataField - unknown aggregation function" );
604 aPropSet
.setProperty( PROP_Function
, eAggFunc
);
606 // field reference ('show data as')
607 DataPilotFieldReference aReference
;
608 aReference
.ReferenceType
= DataPilotFieldReferenceType::NONE
;
609 switch( rDataField
.mnShowDataAs
)
611 case XML_difference
: aReference
.ReferenceType
= DataPilotFieldReferenceType::ITEM_DIFFERENCE
; break;
612 case XML_percent
: aReference
.ReferenceType
= DataPilotFieldReferenceType::ITEM_PERCENTAGE
; break;
613 case XML_percentDiff
: aReference
.ReferenceType
= DataPilotFieldReferenceType::ITEM_PERCENTAGE_DIFFERENCE
; break;
614 case XML_runTotal
: aReference
.ReferenceType
= DataPilotFieldReferenceType::RUNNING_TOTAL
; break;
615 case XML_percentOfRow
: aReference
.ReferenceType
= DataPilotFieldReferenceType::ROW_PERCENTAGE
; break;
616 case XML_percentOfCol
: aReference
.ReferenceType
= DataPilotFieldReferenceType::COLUMN_PERCENTAGE
; break;
617 case XML_percentOfTotal
: aReference
.ReferenceType
= DataPilotFieldReferenceType::TOTAL_PERCENTAGE
; break;
618 case XML_index
: aReference
.ReferenceType
= DataPilotFieldReferenceType::INDEX
; break;
620 if( aReference
.ReferenceType
!= DataPilotFieldReferenceType::NONE
)
622 if( const PivotCacheField
* pCacheField
= mrPivotTable
.getCacheField( rDataField
.mnBaseField
) )
624 aReference
.ReferenceField
= pCacheField
->getName();
625 switch( rDataField
.mnBaseItem
)
627 case OOX_PT_PREVIOUS_ITEM
:
628 aReference
.ReferenceItemType
= DataPilotFieldReferenceItemType::PREVIOUS
;
630 case OOX_PT_NEXT_ITEM
:
631 aReference
.ReferenceItemType
= DataPilotFieldReferenceItemType::NEXT
;
634 aReference
.ReferenceItemType
= DataPilotFieldReferenceItemType::NAMED
;
635 if( const PivotCacheItem
* pCacheItem
= pCacheField
->getCacheItem( rDataField
.mnBaseItem
) )
636 aReference
.ReferenceItemName
= pCacheItem
->getName();
638 aPropSet
.setProperty( PROP_Reference
, aReference
);
644 // private --------------------------------------------------------------------
646 Reference
< XDataPilotField
> PivotTableField::convertRowColPageField( sal_Int32 nAxis
)
648 bool bDataLayout
= mnFieldIndex
== OOX_PT_DATALAYOUTFIELD
;
649 Reference
< XDataPilotField
> xDPField
= bDataLayout
? mrPivotTable
.getDataLayoutField() : mrPivotTable
.getDataPilotField( maDPFieldName
);
650 OSL_ENSURE( bDataLayout
|| (nAxis
== maModel
.mnAxis
), "PivotTableField::convertRowColPageField - field axis mismatch" );
654 // TODO: Use this to set properties directly, bypassing the slow uno layer.
655 ScDPObject
* pDPObj
= mrPivotTable
.getDPObject();
657 PropertySet
aPropSet( xDPField
);
660 DataPilotFieldOrientation eFieldOrient
= DataPilotFieldOrientation_HIDDEN
;
663 case XML_axisRow
: eFieldOrient
= DataPilotFieldOrientation_ROW
; break;
664 case XML_axisCol
: eFieldOrient
= DataPilotFieldOrientation_COLUMN
; break;
665 case XML_axisPage
: eFieldOrient
= DataPilotFieldOrientation_PAGE
; break;
667 if( eFieldOrient
!= DataPilotFieldOrientation_HIDDEN
)
668 aPropSet
.setProperty( PROP_Orientation
, eFieldOrient
);
670 // all other settings not for the data layout field
673 /* Field subtotal functions. Ignore the 'defaultSubtotal' flag, if
674 explicit functions are set. This is different behaviour between
675 XML (where 'defaultSubtotal' is set regardless of other
676 functions) and binary formats (where 'defaultSubtotal' is not
677 set if other functions are set). */
678 ::std::vector
< GeneralFunction
> aSubtotals
;
679 /* Order of subtotals is fixed in Excel. Documentation is a little
680 bit confused about which names to use for the count functions.
681 For subtotals, 'countA' means 'count all', and 'count' means
682 'count numbers'. On the other hand, for the data field
683 aggregation function, 'count' means 'count all', and 'countNum'
684 means 'count numbers' (see below). */
685 if( maModel
.mbSumSubtotal
) aSubtotals
.push_back( GeneralFunction_SUM
);
686 if( maModel
.mbCountASubtotal
) aSubtotals
.push_back( GeneralFunction_COUNT
);
687 if( maModel
.mbAverageSubtotal
) aSubtotals
.push_back( GeneralFunction_AVERAGE
);
688 if( maModel
.mbMaxSubtotal
) aSubtotals
.push_back( GeneralFunction_MAX
);
689 if( maModel
.mbMinSubtotal
) aSubtotals
.push_back( GeneralFunction_MIN
);
690 if( maModel
.mbProductSubtotal
) aSubtotals
.push_back( GeneralFunction_PRODUCT
);
691 if( maModel
.mbCountSubtotal
) aSubtotals
.push_back( GeneralFunction_COUNTNUMS
);
692 if( maModel
.mbStdDevSubtotal
) aSubtotals
.push_back( GeneralFunction_STDEV
);
693 if( maModel
.mbStdDevPSubtotal
) aSubtotals
.push_back( GeneralFunction_STDEVP
);
694 if( maModel
.mbVarSubtotal
) aSubtotals
.push_back( GeneralFunction_VAR
);
695 if( maModel
.mbVarPSubtotal
) aSubtotals
.push_back( GeneralFunction_VARP
);
696 // if no function is set manually, check the 'defaultSubtotal' flag
697 if( aSubtotals
.empty() && maModel
.mbDefaultSubtotal
)
698 aSubtotals
.push_back( GeneralFunction_AUTO
);
699 aPropSet
.setProperty( PROP_Subtotals
, ContainerHelper::vectorToSequence( aSubtotals
) );
702 DataPilotFieldLayoutInfo aLayoutInfo
;
703 aLayoutInfo
.LayoutMode
= maModel
.mbOutline
?
704 (maModel
.mbSubtotalTop
? DataPilotFieldLayoutMode::OUTLINE_SUBTOTALS_TOP
: DataPilotFieldLayoutMode::OUTLINE_SUBTOTALS_BOTTOM
) :
705 DataPilotFieldLayoutMode::TABULAR_LAYOUT
;
706 aLayoutInfo
.AddEmptyLines
= maModel
.mbInsertBlankRow
;
707 aPropSet
.setProperty( PROP_LayoutInfo
, aLayoutInfo
);
708 aPropSet
.setProperty( PROP_ShowEmpty
, maModel
.mbShowAll
);
710 // auto show (OOXML/BIFF12 only)
711 if( maModel
.mbAutoShow
)
713 DataPilotFieldAutoShowInfo aAutoShowInfo
;
714 aAutoShowInfo
.IsEnabled
= true;
715 aAutoShowInfo
.ShowItemsMode
= maModel
.mbTopAutoShow
? DataPilotFieldShowItemsMode::FROM_TOP
: DataPilotFieldShowItemsMode::FROM_BOTTOM
;
716 aAutoShowInfo
.ItemCount
= maModel
.mnAutoShowItems
;
717 if( const PivotCacheField
* pCacheField
= mrPivotTable
.getCacheFieldOfDataField( maModel
.mnAutoShowRankBy
) )
718 aAutoShowInfo
.DataField
= pCacheField
->getName();
719 aPropSet
.setProperty( PROP_AutoShowInfo
, aAutoShowInfo
);
723 DataPilotFieldSortInfo aSortInfo
;
724 aSortInfo
.IsAscending
= maModel
.mnSortType
== XML_ascending
;
725 if( (maModel
.mnSortType
!= XML_ascending
) && (maModel
.mnSortType
!= XML_descending
) )
727 aSortInfo
.Mode
= DataPilotFieldSortMode::MANUAL
;
731 const PivotCacheField
* pCacheField
= (maModel
.mnSortRefField
== OOX_PT_DATALAYOUTFIELD
) ?
732 mrPivotTable
.getCacheFieldOfDataField( maModel
.mnSortRefItem
) : nullptr;
735 aSortInfo
.Mode
= DataPilotFieldSortMode::DATA
;
736 aSortInfo
.Field
= pCacheField
->getName();
740 aSortInfo
.Mode
= DataPilotFieldSortMode::NAME
;
743 aPropSet
.setProperty( PROP_SortInfo
, aSortInfo
);
746 if (const PivotCacheField
* pCacheField
= mrPivotTable
.getCacheField(mnFieldIndex
))
748 ScDPSaveData
* pSaveData
= pDPObj
->GetSaveData();
749 ScDPSaveDimension
* pDim
= pSaveData
->GetDimensionByName(pCacheField
->getName());
753 for( const auto& rItem
: maItems
)
755 if (rItem
.mnType
!= XML_data
)
758 const PivotCacheItem
* pSharedItem
= pCacheField
->getCacheItem(rItem
.mnCacheItem
);
764 ScDPSaveMember
* pMem
= pDim
->GetMemberByName(pSharedItem
->getFormattedName(*pDim
, pDPObj
, DateTime(getWorkbookSettings().getNullDate())));
765 pMem
->SetShowDetails(rItem
.mbShowDetails
);
766 pMem
->SetIsVisible(!rItem
.mbHidden
);
770 // catch every failed container access to be able to process following items
774 catch (const Exception
&) {}
781 PTFilterModel::PTFilterModel() :
784 mnMemPropField( -1 ),
785 mnType( XML_TOKEN_INVALID
),
788 mnMeasureField( -1 ),
794 PivotTableFilter::PivotTableFilter( const PivotTable
& rPivotTable
) :
795 WorkbookHelper( rPivotTable
),
796 mrPivotTable( rPivotTable
)
800 void PivotTableFilter::importFilter( const AttributeList
& rAttribs
)
802 maModel
.maName
= rAttribs
.getXString( XML_name
, OUString() );
803 maModel
.maDescription
= rAttribs
.getXString( XML_description
, OUString() );
804 maModel
.maStrValue1
= rAttribs
.getXString( XML_stringValue1
, OUString() );
805 maModel
.maStrValue2
= rAttribs
.getXString( XML_stringValue2
, OUString() );
806 maModel
.mnField
= rAttribs
.getInteger( XML_fld
, -1 );
807 maModel
.mnMemPropField
= rAttribs
.getInteger( XML_mpFld
, -1 );
808 maModel
.mnType
= rAttribs
.getToken( XML_type
, XML_TOKEN_INVALID
);
809 maModel
.mnEvalOrder
= rAttribs
.getInteger( XML_evalOrder
, 0 );
810 maModel
.mnId
= rAttribs
.getInteger( XML_id
, -1 );
811 maModel
.mnMeasureField
= rAttribs
.getInteger( XML_iMeasureFld
, -1 );
812 maModel
.mnMeasureHier
= rAttribs
.getInteger( XML_iMeasureHier
, -1 );
815 void PivotTableFilter::importTop10( const AttributeList
& rAttribs
)
817 OSL_ENSURE( rAttribs
.getBool( XML_percent
, false ) == (maModel
.mnType
== XML_percent
),
818 "PivotTableFilter::importTop10 - unexpected value of percent attribute" );
819 maModel
.mfValue
= rAttribs
.getDouble( XML_val
, 0.0 );
820 maModel
.mbTopFilter
= rAttribs
.getBool( XML_top
, true );
823 void PivotTableFilter::importPTFilter( SequenceInputStream
& rStrm
)
827 maModel
.mnField
= rStrm
.readInt32();
828 maModel
.mnMemPropField
= rStrm
.readInt32();
829 nType
= rStrm
.readInt32();
830 rStrm
.skip( 4 ); // unused
831 maModel
.mnId
= rStrm
.readInt32();
832 maModel
.mnMeasureField
= rStrm
.readInt32();
833 maModel
.mnMeasureHier
= rStrm
.readInt32();
834 nFlags
= rStrm
.readuInt16();
835 if( getFlag( nFlags
, BIFF12_PTFILTER_HASNAME
) )
836 rStrm
>> maModel
.maName
;
837 if( getFlag( nFlags
, BIFF12_PTFILTER_HASDESCRIPTION
) )
838 rStrm
>> maModel
.maDescription
;
839 if( getFlag( nFlags
, BIFF12_PTFILTER_HASSTRVALUE1
) )
840 rStrm
>> maModel
.maStrValue1
;
841 if( getFlag( nFlags
, BIFF12_PTFILTER_HASSTRVALUE2
) )
842 rStrm
>> maModel
.maStrValue2
;
844 static const sal_Int32 spnTypes
[] =
847 // data field top10 filter (1-3)
848 XML_count
, XML_percent
, XML_sum
,
849 // caption filter (4-17)
850 XML_captionEqual
, XML_captionNotEqual
,
851 XML_captionBeginsWith
, XML_captionNotBeginsWith
, XML_captionEndsWith
, XML_captionNotEndsWith
,
852 XML_captionContains
, XML_captionNotContains
, XML_captionGreaterThan
, XML_captionGreaterThanOrEqual
,
853 XML_captionLessThan
, XML_captionLessThanOrEqual
, XML_captionBetween
, XML_captionNotBetween
,
854 // value filter (18-25)
855 XML_valueEqual
, XML_valueNotEqual
, XML_valueGreaterThan
, XML_valueGreaterThanOrEqual
,
856 XML_valueLessThan
, XML_valueLessThanOrEqual
, XML_valueBetween
, XML_valueNotBetween
,
857 // date filter (26-65)
858 XML_dateEqual
, XML_dateOlderThan
, XML_dateNewerThan
, XML_dateBetween
,
859 XML_tomorrow
, XML_today
, XML_yesterday
, XML_nextWeek
, XML_thisWeek
, XML_lastWeek
,
860 XML_nextMonth
, XML_thisMonth
, XML_lastMonth
, XML_nextQuarter
, XML_thisQuarter
, XML_lastQuarter
,
861 XML_nextYear
, XML_thisYear
, XML_lastYear
, XML_yearToDate
, XML_Q1
, XML_Q2
, XML_Q3
, XML_Q4
,
862 XML_M1
, XML_M2
, XML_M3
, XML_M4
, XML_M5
, XML_M6
, XML_M7
, XML_M8
, XML_M9
, XML_M10
, XML_M11
, XML_M12
,
863 XML_dateNotEqual
, XML_dateOlderThanOrEqual
, XML_dateNewerThanOrEqual
, XML_dateNotBetween
865 maModel
.mnType
= STATIC_ARRAY_SELECT( spnTypes
, nType
, XML_TOKEN_INVALID
);
868 void PivotTableFilter::importTop10Filter( SequenceInputStream
& rStrm
)
871 nFlags
= rStrm
.readuChar();
872 maModel
.mfValue
= rStrm
.readDouble();
875 getFlag(nFlags
, BIFF12_TOP10FILTER_PERCENT
) != (maModel
.mnType
== XML_percent
),
877 "PivotTableFilter::importTop10 - unexpected value of percent attribute");
878 maModel
.mbTopFilter
= getFlag( nFlags
, BIFF12_TOP10FILTER_TOP
);
881 void PivotTableFilter::finalizeImport()
883 // only simple top10 filter supported
884 if( maModel
.mnType
== XML_count
)
886 PropertySet
aPropSet( mrPivotTable
.getDataPilotField( maModel
.mnField
) );
889 DataPilotFieldAutoShowInfo aAutoShowInfo
;
890 aAutoShowInfo
.IsEnabled
= true;
891 aAutoShowInfo
.ShowItemsMode
= maModel
.mbTopFilter
? DataPilotFieldShowItemsMode::FROM_TOP
: DataPilotFieldShowItemsMode::FROM_BOTTOM
;
892 aAutoShowInfo
.ItemCount
= getLimitedValue
< sal_Int32
, double >( maModel
.mfValue
, 0, SAL_MAX_INT32
);
893 if( const PivotCacheField
* pCacheField
= mrPivotTable
.getCacheFieldOfDataField( maModel
.mnMeasureField
) )
894 aAutoShowInfo
.DataField
= pCacheField
->getName();
895 aPropSet
.setProperty( PROP_AutoShowInfo
, aAutoShowInfo
);
900 PTDefinitionModel::PTDefinitionModel() :
906 mbDataOnRows( false ),
907 mbShowError( false ),
908 mbShowMissing( true ),
910 mbDisableFieldList( false ),
911 mbShowCalcMembers( true ),
912 mbVisualTotals( true ),
914 mbPrintDrill( false ),
915 mbEnableDrill( true ),
916 mbPreserveFormatting( true ),
917 mbUseAutoFormat( false ),
918 mbPageOverThenDown( false ),
919 mbSubtotalHiddenItems( false ),
920 mbRowGrandTotals( true ),
921 mbColGrandTotals( true ),
922 mbFieldPrintTitles( false ),
923 mbItemPrintTitles( false ),
924 mbMergeItem( false ),
925 mbShowEmptyRow( false ),
926 mbShowEmptyCol( false ),
927 mbShowHeaders( true ),
928 mbFieldListSortAsc( false ),
929 mbCustomListSort( true )
933 PTLocationModel::PTLocationModel() :
934 mnFirstHeaderRow( 0 ),
942 PivotTable::PivotTable( const WorkbookHelper
& rHelper
) :
943 WorkbookHelper( rHelper
),
945 maDataField( *this, OOX_PT_DATALAYOUTFIELD
),
946 mpPivotCache( nullptr )
950 void PivotTable::importPivotTableDefinition( const AttributeList
& rAttribs
)
952 maDefModel
.maName
= rAttribs
.getXString( XML_name
, OUString() );
953 maDefModel
.maDataCaption
= rAttribs
.getXString( XML_dataCaption
, OUString() );
954 maDefModel
.maGrandTotalCaption
= rAttribs
.getXString( XML_grandTotalCaption
, OUString() );
955 maDefModel
.maRowHeaderCaption
= rAttribs
.getXString( XML_rowHeaderCaption
, OUString() );
956 maDefModel
.maColHeaderCaption
= rAttribs
.getXString( XML_colHeaderCaption
, OUString() );
957 maDefModel
.maErrorCaption
= rAttribs
.getXString( XML_errorCaption
, OUString() );
958 maDefModel
.maMissingCaption
= rAttribs
.getXString( XML_missingCaption
, OUString() );
959 maDefModel
.maPageStyle
= rAttribs
.getXString( XML_pageStyle
, OUString() );
960 maDefModel
.maPivotTableStyle
= rAttribs
.getXString( XML_pivotTableStyle
, OUString() );
961 maDefModel
.maVacatedStyle
= rAttribs
.getXString( XML_vacatedStyle
, OUString() );
962 maDefModel
.maTag
= rAttribs
.getXString( XML_tag
, OUString() );
963 maDefModel
.mnCacheId
= rAttribs
.getInteger( XML_cacheId
, -1 );
964 maDefModel
.mnDataPosition
= rAttribs
.getInteger( XML_dataPosition
, 0 );
965 maDefModel
.mnPageWrap
= rAttribs
.getInteger( XML_pageWrap
, 0 );
966 maDefModel
.mnIndent
= rAttribs
.getInteger( XML_indent
, 1 );
967 maDefModel
.mnChartFormat
= rAttribs
.getInteger( XML_chartFormat
, 0 );
968 maDefModel
.mnAutoFormatId
= rAttribs
.getInteger( XML_autoFormatId
, 0 );
969 maDefModel
.mbDataOnRows
= rAttribs
.getBool( XML_dataOnRows
, false );
970 maDefModel
.mbShowError
= rAttribs
.getBool( XML_showError
, false );
971 maDefModel
.mbShowMissing
= rAttribs
.getBool( XML_showMissing
, true );
972 maDefModel
.mbShowItems
= rAttribs
.getBool( XML_showItems
, true );
973 maDefModel
.mbDisableFieldList
= rAttribs
.getBool( XML_disableFieldList
, false );
974 maDefModel
.mbShowCalcMembers
= rAttribs
.getBool( XML_showCalcMbrs
, true );
975 maDefModel
.mbVisualTotals
= rAttribs
.getBool( XML_visualTotals
, true );
976 maDefModel
.mbShowDrill
= rAttribs
.getBool( XML_showDrill
, true );
977 maDefModel
.mbPrintDrill
= rAttribs
.getBool( XML_printDrill
, false );
978 maDefModel
.mbEnableDrill
= rAttribs
.getBool( XML_enableDrill
, true );
979 maDefModel
.mbPreserveFormatting
= rAttribs
.getBool( XML_preserveFormatting
, true );
980 maDefModel
.mbUseAutoFormat
= rAttribs
.getBool( XML_useAutoFormatting
, false );
981 maDefModel
.mbPageOverThenDown
= rAttribs
.getBool( XML_pageOverThenDown
, false );
982 maDefModel
.mbSubtotalHiddenItems
= rAttribs
.getBool( XML_subtotalHiddenItems
, false );
983 maDefModel
.mbRowGrandTotals
= rAttribs
.getBool( XML_rowGrandTotals
, true );
984 maDefModel
.mbColGrandTotals
= rAttribs
.getBool( XML_colGrandTotals
, true );
985 maDefModel
.mbFieldPrintTitles
= rAttribs
.getBool( XML_fieldPrintTitles
, false );
986 maDefModel
.mbItemPrintTitles
= rAttribs
.getBool( XML_itemPrintTitles
, false );
987 maDefModel
.mbMergeItem
= rAttribs
.getBool( XML_mergeItem
, false );
988 maDefModel
.mbShowEmptyRow
= rAttribs
.getBool( XML_showEmptyRow
, false );
989 maDefModel
.mbShowEmptyCol
= rAttribs
.getBool( XML_showEmptyCol
, false );
990 maDefModel
.mbShowHeaders
= rAttribs
.getBool( XML_showHeaders
, true );
991 maDefModel
.mbFieldListSortAsc
= rAttribs
.getBool( XML_fieldListSortAscending
, false );
992 maDefModel
.mbCustomListSort
= rAttribs
.getBool( XML_customListSort
, true );
993 maDefModel
.mbApplyNumFmt
= rAttribs
.getBool( XML_applyNumberFormats
, false );
994 maDefModel
.mbApplyFont
= rAttribs
.getBool( XML_applyFontFormats
, false );
995 maDefModel
.mbApplyAlignment
= rAttribs
.getBool( XML_applyAlignmentFormats
, false );
996 maDefModel
.mbApplyBorder
= rAttribs
.getBool( XML_applyBorderFormats
, false );
997 maDefModel
.mbApplyFill
= rAttribs
.getBool( XML_applyPatternFormats
, false );
998 // OOXML and BIFF12 documentation differ: OOXML mentions width/height, BIFF12 mentions protection
999 maDefModel
.mbApplyProtection
= rAttribs
.getBool( XML_applyWidthHeightFormats
, false );
1002 void PivotTable::importLocation( const AttributeList
& rAttribs
, sal_Int16 nSheet
)
1004 AddressConverter::convertToCellRangeUnchecked( maLocationModel
.maRange
, rAttribs
.getString( XML_ref
, OUString() ), nSheet
);
1005 maLocationModel
.mnFirstHeaderRow
= rAttribs
.getInteger( XML_firstHeaderRow
, 0 );
1006 maLocationModel
.mnFirstDataRow
= rAttribs
.getInteger( XML_firstDataRow
, 0 );
1007 maLocationModel
.mnFirstDataCol
= rAttribs
.getInteger( XML_firstDataCol
, 0 );
1008 maLocationModel
.mnRowPageCount
= rAttribs
.getInteger( XML_rowPageCount
, 0 );
1009 maLocationModel
.mnColPageCount
= rAttribs
.getInteger( XML_colPageCount
, 0 );
1012 void PivotTable::importRowField( const AttributeList
& rAttribs
)
1014 importField( maRowFields
, rAttribs
);
1017 void PivotTable::importColField( const AttributeList
& rAttribs
)
1019 importField( maColFields
, rAttribs
);
1022 void PivotTable::importPageField( const AttributeList
& rAttribs
)
1024 PTPageFieldModel aModel
;
1025 aModel
.maName
= rAttribs
.getXString( XML_name
, OUString() );
1026 aModel
.mnField
= rAttribs
.getInteger( XML_fld
, -1 );
1027 // specification is wrong, XML_item is not the cache item, but the field item
1028 aModel
.mnItem
= rAttribs
.getInteger( XML_item
, BIFF12_PTPAGEFIELD_MULTIITEMS
);
1029 maPageFields
.push_back( aModel
);
1032 void PivotTable::importDataField( const AttributeList
& rAttribs
)
1034 PTDataFieldModel aModel
;
1035 aModel
.maName
= rAttribs
.getXString( XML_name
, OUString() );
1036 aModel
.mnField
= rAttribs
.getInteger( XML_fld
, -1 );
1037 aModel
.mnSubtotal
= rAttribs
.getToken( XML_subtotal
, XML_sum
);
1038 aModel
.mnShowDataAs
= rAttribs
.getToken( XML_showDataAs
, XML_normal
);
1039 aModel
.mnBaseField
= rAttribs
.getInteger( XML_baseField
, -1 );
1040 aModel
.mnBaseItem
= rAttribs
.getInteger( XML_baseItem
, -1 );
1041 aModel
.mnNumFmtId
= rAttribs
.getInteger( XML_numFmtId
, 0 );
1042 maDataFields
.push_back( aModel
);
1045 void PivotTable::putToInteropGrabBag(const OUString
& sName
, const AttributeList
& rAttribs
)
1047 if (auto xFastAttributeList
= rAttribs
.getFastAttributeList())
1049 // Store both known and unknown attribute sequences to the grab bag as is
1050 css::uno::Sequence
<css::xml::FastAttribute
> aFast
= xFastAttributeList
->getFastAttributes();
1051 css::uno::Sequence
<css::xml::Attribute
> aUnk
= xFastAttributeList
->getUnknownAttributes();
1052 css::uno::Sequence
<css::uno::Any
> aVal
{ css::uno::Any(aFast
), css::uno::Any(aUnk
) };
1053 maInteropGrabBag
[sName
] <<= aVal
;
1057 void PivotTable::importPTDefinition( SequenceInputStream
& rStrm
)
1059 sal_uInt32 nFlags1
, nFlags2
, nFlags3
;
1060 sal_uInt8 nDataAxis
;
1061 nFlags1
= rStrm
.readuInt32();
1062 nFlags2
= rStrm
.readuInt32();
1063 nFlags3
= rStrm
.readuInt32();
1064 nDataAxis
= rStrm
.readuChar();
1065 maDefModel
.mnPageWrap
= rStrm
.readuInt8();
1066 rStrm
.skip( 2 ); // refresh versions
1067 maDefModel
.mnDataPosition
= rStrm
.readInt32();
1068 maDefModel
.mnAutoFormatId
= rStrm
.readuInt16();
1069 rStrm
.skip( 2 ); // unused
1070 maDefModel
.mnChartFormat
= rStrm
.readInt32();
1071 maDefModel
.mnCacheId
= rStrm
.readInt32();
1072 rStrm
>> maDefModel
.maName
;
1073 if( getFlag( nFlags2
, BIFF12_PTDEF_HASDATACAPTION
) )
1074 rStrm
>> maDefModel
.maDataCaption
;
1075 if( getFlag( nFlags2
, BIFF12_PTDEF_HASGRANDTOTALCAPTION
) )
1076 rStrm
>> maDefModel
.maGrandTotalCaption
;
1077 if( !getFlag( nFlags3
, BIFF12_PTDEF_NOERRORCAPTION
) ) // missing flag indicates existing string
1078 rStrm
>> maDefModel
.maErrorCaption
;
1079 if( !getFlag( nFlags3
, BIFF12_PTDEF_NOMISSINGCAPTION
) ) // missing flag indicates existing string
1080 rStrm
>> maDefModel
.maMissingCaption
;
1081 if( getFlag( nFlags2
, BIFF12_PTDEF_HASPAGESTYLE
) )
1082 rStrm
>> maDefModel
.maPageStyle
;
1083 if( getFlag( nFlags2
, BIFF12_PTDEF_HASPIVOTTABLESTYLE
) )
1084 rStrm
>> maDefModel
.maPivotTableStyle
;
1085 if( getFlag( nFlags2
, BIFF12_PTDEF_HASVACATEDSTYLE
) )
1086 rStrm
>> maDefModel
.maVacatedStyle
;
1087 if( getFlag( nFlags2
, BIFF12_PTDEF_HASTAG
) )
1088 rStrm
>> maDefModel
.maTag
;
1089 if( getFlag( nFlags3
, BIFF12_PTDEF_HASCOLHEADERCAPTION
) ) // TODO: right order (col/row)? spec is unclear
1090 rStrm
>> maDefModel
.maColHeaderCaption
;
1091 if( getFlag( nFlags3
, BIFF12_PTDEF_HASROWHEADERCAPTION
) )
1092 rStrm
>> maDefModel
.maRowHeaderCaption
;
1095 (nDataAxis
!= BIFF12_PTDEF_ROWAXIS
) && (nDataAxis
!= BIFF12_PTDEF_COLAXIS
),
1097 "PivotTable::importPTDefinition - unexpected axis position for data field");
1099 maDefModel
.mnIndent
= extractValue
< sal_uInt8
>( nFlags1
, 24, 7 );
1100 maDefModel
.mbDataOnRows
= nDataAxis
== BIFF12_PTDEF_ROWAXIS
;
1101 maDefModel
.mbShowError
= getFlag( nFlags2
, BIFF12_PTDEF_SHOWERROR
);
1102 maDefModel
.mbShowMissing
= getFlag( nFlags2
, BIFF12_PTDEF_SHOWMISSING
);
1103 maDefModel
.mbShowItems
= getFlag( nFlags1
, BIFF12_PTDEF_SHOWITEMS
);
1104 maDefModel
.mbDisableFieldList
= getFlag( nFlags1
, BIFF12_PTDEF_DISABLEFIELDLIST
);
1105 maDefModel
.mbShowCalcMembers
= !getFlag( nFlags1
, BIFF12_PTDEF_HIDECALCMEMBERS
);
1106 maDefModel
.mbVisualTotals
= !getFlag( nFlags1
, BIFF12_PTDEF_WITHHIDDENTOTALS
);
1107 maDefModel
.mbShowDrill
= !getFlag( nFlags1
, BIFF12_PTDEF_HIDEDRILL
);
1108 maDefModel
.mbPrintDrill
= getFlag( nFlags1
, BIFF12_PTDEF_PRINTDRILL
);
1109 maDefModel
.mbEnableDrill
= getFlag( nFlags2
, BIFF12_PTDEF_ENABLEDRILL
);
1110 maDefModel
.mbPreserveFormatting
= getFlag( nFlags2
, BIFF12_PTDEF_PRESERVEFORMATTING
);
1111 maDefModel
.mbUseAutoFormat
= getFlag( nFlags2
, BIFF12_PTDEF_USEAUTOFORMAT
);
1112 maDefModel
.mbPageOverThenDown
= getFlag( nFlags2
, BIFF12_PTDEF_PAGEOVERTHENDOWN
);
1113 maDefModel
.mbSubtotalHiddenItems
= getFlag( nFlags2
, BIFF12_PTDEF_SUBTOTALHIDDENITEMS
);
1114 maDefModel
.mbRowGrandTotals
= getFlag( nFlags2
, BIFF12_PTDEF_ROWGRANDTOTALS
);
1115 maDefModel
.mbColGrandTotals
= getFlag( nFlags2
, BIFF12_PTDEF_COLGRANDTOTALS
);
1116 maDefModel
.mbFieldPrintTitles
= getFlag( nFlags2
, BIFF12_PTDEF_FIELDPRINTTITLES
);
1117 maDefModel
.mbItemPrintTitles
= getFlag( nFlags2
, BIFF12_PTDEF_ITEMPRINTTITLES
);
1118 maDefModel
.mbMergeItem
= getFlag( nFlags2
, BIFF12_PTDEF_MERGEITEM
);
1119 maDefModel
.mbApplyNumFmt
= getFlag( nFlags2
, BIFF12_PTDEF_APPLYNUMFMT
);
1120 maDefModel
.mbApplyFont
= getFlag( nFlags2
, BIFF12_PTDEF_APPLYFONT
);
1121 maDefModel
.mbApplyAlignment
= getFlag( nFlags2
, BIFF12_PTDEF_APPLYALIGNMENT
);
1122 maDefModel
.mbApplyBorder
= getFlag( nFlags2
, BIFF12_PTDEF_APPLYBORDER
);
1123 maDefModel
.mbApplyFill
= getFlag( nFlags2
, BIFF12_PTDEF_APPLYFILL
);
1124 maDefModel
.mbApplyProtection
= getFlag( nFlags2
, BIFF12_PTDEF_APPLYPROTECTION
);
1125 maDefModel
.mbShowEmptyRow
= getFlag( nFlags2
, BIFF12_PTDEF_SHOWEMPTYROW
);
1126 maDefModel
.mbShowEmptyCol
= getFlag( nFlags2
, BIFF12_PTDEF_SHOWEMPTYCOL
);
1127 maDefModel
.mbShowHeaders
= !getFlag( nFlags1
, BIFF12_PTDEF_HIDEHEADERS
);
1128 maDefModel
.mbFieldListSortAsc
= getFlag( nFlags3
, BIFF12_PTDEF_FIELDLISTSORTASC
);
1129 maDefModel
.mbCustomListSort
= !getFlag( nFlags3
, BIFF12_PTDEF_NOCUSTOMLISTSORT
);
1132 void PivotTable::importPTLocation( SequenceInputStream
& rStrm
, sal_Int16 nSheet
)
1136 maLocationModel
.mnFirstHeaderRow
= rStrm
.readInt32();
1137 maLocationModel
.mnFirstDataRow
= rStrm
.readInt32();
1138 maLocationModel
.mnFirstDataCol
= rStrm
.readInt32();
1139 maLocationModel
.mnRowPageCount
= rStrm
.readInt32();
1140 maLocationModel
.mnColPageCount
= rStrm
.readInt32();
1141 AddressConverter::convertToCellRangeUnchecked( maLocationModel
.maRange
, aBinRange
, nSheet
);
1144 void PivotTable::importPTRowFields( SequenceInputStream
& rStrm
)
1146 importFields( maRowFields
, rStrm
);
1149 void PivotTable::importPTColFields( SequenceInputStream
& rStrm
)
1151 importFields( maColFields
, rStrm
);
1154 void PivotTable::importPTPageField( SequenceInputStream
& rStrm
)
1156 PTPageFieldModel aModel
;
1158 aModel
.mnField
= rStrm
.readInt32();
1159 aModel
.mnItem
= rStrm
.readInt32();
1160 rStrm
.skip( 4 ); // hierarchy
1161 nFlags
= rStrm
.readuChar();
1162 if( getFlag( nFlags
, BIFF12_PTPAGEFIELD_HASNAME
) )
1163 rStrm
>> aModel
.maName
;
1164 maPageFields
.push_back( aModel
);
1167 void PivotTable::importPTDataField( SequenceInputStream
& rStrm
)
1169 PTDataFieldModel aModel
;
1170 sal_Int32 nSubtotal
, nShowDataAs
;
1172 aModel
.mnField
= rStrm
.readInt32( );
1173 nSubtotal
= rStrm
.readInt32();
1174 nShowDataAs
= rStrm
.readInt32();
1175 aModel
.mnBaseField
= rStrm
.readInt32();
1176 aModel
.mnBaseItem
= rStrm
.readInt32();
1177 aModel
.mnNumFmtId
= rStrm
.readInt32();
1178 nHasName
= rStrm
.readuChar();
1180 rStrm
>> aModel
.maName
;
1181 aModel
.setBiffSubtotal( nSubtotal
);
1182 aModel
.setBiffShowDataAs( nShowDataAs
);
1183 maDataFields
.push_back( aModel
);
1186 PivotTableField
& PivotTable::createTableField()
1188 sal_Int32 nFieldIndex
= static_cast< sal_Int32
>( maFields
.size() );
1189 PivotTableFieldVector::value_type
xTableField( new PivotTableField( *this, nFieldIndex
) );
1190 maFields
.push_back( xTableField
);
1191 return *xTableField
;
1194 PivotTableFilter
& PivotTable::createTableFilter()
1196 PivotTableFilterVector::value_type
xTableFilter( new PivotTableFilter( *this ) );
1197 maFilters
.push_back( xTableFilter
);
1198 return *xTableFilter
;
1201 void PivotTable::finalizeImport()
1203 if( getAddressConverter().validateCellRange( maLocationModel
.maRange
, true, true ) )
1205 mpPivotCache
= getPivotCaches().importPivotCacheFragment( maDefModel
.mnCacheId
);
1206 if( mpPivotCache
&& mpPivotCache
->isValidDataSource() && !maDefModel
.maName
.isEmpty() )
1208 // clear destination area of the original pivot table
1211 Reference
< XSheetOperation
> xSheetOp( getCellRangeFromDoc( maLocationModel
.maRange
), UNO_QUERY_THROW
);
1212 using namespace ::com::sun::star::sheet::CellFlags
;
1213 xSheetOp
->clearContents( VALUE
| DATETIME
| STRING
| FORMULA
| HARDATTR
| STYLES
| EDITATTR
| FORMATTED
);
1221 // create a new data pilot descriptor based on the source data
1222 Reference
< XDataPilotTablesSupplier
> xDPTablesSupp( getSheetFromDoc( maLocationModel
.maRange
.aStart
.Tab() ), UNO_QUERY_THROW
);
1223 Reference
< XDataPilotTables
> xDPTables( xDPTablesSupp
->getDataPilotTables(), UNO_SET_THROW
);
1224 mxDPDescriptor
.set( xDPTables
->createDataPilotDescriptor(), UNO_SET_THROW
);
1225 ScRange aRange
= mpPivotCache
->getSourceRange();
1226 CellRangeAddress
aCellRangeAddress( aRange
.aStart
.Tab(),
1227 aRange
.aStart
.Col(), aRange
.aStart
.Row(),
1228 aRange
.aEnd
.Col(), aRange
.aEnd
.Row() );
1229 mxDPDescriptor
->setSourceRange( aCellRangeAddress
);
1230 mxDPDescriptor
->setTag( maDefModel
.maTag
);
1232 // TODO: This is a hack. Eventually we need to convert the whole thing to the internal API.
1233 auto pImpl
= comphelper::getUnoTunnelImplementation
<ScDataPilotDescriptorBase
>(mxDPDescriptor
);
1237 mpDPObject
= pImpl
->GetDPObject();
1241 // global data pilot properties
1242 PropertySet
aDescProp( mxDPDescriptor
);
1243 aDescProp
.setProperty( PROP_ColumnGrand
, maDefModel
.mbColGrandTotals
);
1244 aDescProp
.setProperty( PROP_RowGrand
, maDefModel
.mbRowGrandTotals
);
1245 aDescProp
.setProperty( PROP_ShowFilterButton
, false );
1246 aDescProp
.setProperty( PROP_DrillDownOnDoubleClick
, maDefModel
.mbEnableDrill
);
1248 // finalize all fields, this finds field names and creates grouping fields
1249 finalizeFieldsImport();
1252 for( const auto& rRowField
: maRowFields
)
1253 if( PivotTableField
* pField
= getTableField( rRowField
) )
1254 pField
->convertRowField();
1256 // all column fields
1257 for( const auto& rColField
: maColFields
)
1258 if( PivotTableField
* pField
= getTableField( rColField
) )
1259 pField
->convertColField();
1262 for( const auto& rPageField
: maPageFields
)
1263 if( PivotTableField
* pField
= getTableField( rPageField
.mnField
) )
1264 pField
->convertPageField( rPageField
);
1266 // all hidden fields
1267 ::std::set
< sal_Int32
> aVisFields
;
1268 aVisFields
.insert( maRowFields
.begin(), maRowFields
.end() );
1269 aVisFields
.insert( maColFields
.begin(), maColFields
.end() );
1270 for( const auto& rPageField
: maPageFields
)
1271 aVisFields
.insert( rPageField
.mnField
);
1272 sal_Int32 nIndex
= 0;
1273 for( auto& rxField
: maFields
)
1275 if( aVisFields
.count( nIndex
) == 0 )
1276 rxField
->convertHiddenField();
1281 for( auto& rDataField
: maDataFields
)
1283 if( const PivotCacheField
* pCacheField
= getCacheField( rDataField
.mnField
) )
1285 if ( pCacheField
-> getGroupBaseField() != -1 )
1286 rDataField
.mnField
= pCacheField
-> getGroupBaseField();
1288 if( PivotTableField
* pField
= getTableField( rDataField
.mnField
) )
1289 pField
->convertDataField( rDataField
);
1293 maFilters
.forEachMem( &PivotTableFilter::finalizeImport
);
1295 // calculate base position of table
1296 CellAddress
aPos( maLocationModel
.maRange
.aStart
.Tab(), maLocationModel
.maRange
.aStart
.Col(), maLocationModel
.maRange
.aStart
.Row() );
1297 /* If page fields exist, include them into the destination
1298 area (they are excluded in Excel). Add an extra blank row. */
1299 if( !maPageFields
.empty() )
1300 aPos
.Row
= ::std::max
< sal_Int32
>( static_cast< sal_Int32
>( aPos
.Row
- maPageFields
.size() - 1 ), 0 );
1302 // save interop grab bag
1303 mpDPObject
->PutInteropGrabBag(std::move(maInteropGrabBag
));
1305 // insert the DataPilot table into the sheet
1306 xDPTables
->insertNewByName( maDefModel
.maName
, aPos
, mxDPDescriptor
);
1310 OSL_FAIL( "PivotTable::finalizeImport - exception while creating the DataPilot table" );
1316 void PivotTable::finalizeFieldsImport()
1318 if (maFields
.empty())
1321 /* Check whether group fields are already imported for another table
1322 sharing the same groups. */
1323 ScDPObject
* pDPObj
= getDPObject();
1324 const ScDocument
& rDoc
= getDocImport().getDoc();
1325 if (rDoc
.HasPivotTable())
1327 const ScDPCollection
* pDPCollection
= rDoc
.GetDPCollection();
1328 assert(pDPCollection
!= nullptr);
1329 const ScDPDimensionSaveData
* pGroups
= nullptr;
1330 bool bRefFound
= pDPCollection
->GetReferenceGroups(*pDPObj
, &pGroups
);
1331 // Apply reference groups on this table.
1332 if (bRefFound
&& pGroups
&& pGroups
->HasGroupDimensions()) {
1333 ScDPSaveData
* pSaveData
= pDPObj
->GetSaveData();
1335 pSaveData
->SetDimensionData(pGroups
);
1336 pDPObj
->ReloadGroupTableData();
1337 maFields
.forEachMem(&PivotTableField::finalizeImportBasedOnCache
, ::std::cref(mxDPDescriptor
));
1343 maFields
.forEachMem(&PivotTableField::finalizeImport
, ::std::cref(mxDPDescriptor
));
1346 void PivotTable::finalizeDateGroupingImport( const Reference
< XDataPilotField
>& rxBaseDPField
, sal_Int32 nBaseFieldIdx
)
1348 // process all fields, there is no chaining information in the cache fields
1349 maFields
.forEachMem( &PivotTableField::finalizeDateGroupingImport
, ::std::cref(rxBaseDPField
), nBaseFieldIdx
);
1352 void PivotTable::finalizeParentGroupingImport( const Reference
< XDataPilotField
>& rxBaseDPField
,
1353 const PivotCacheField
& rBaseCacheField
, PivotCacheGroupItemVector
& orItemNames
)
1355 // try to create parent group fields that group the items of the passed base field
1356 if( PivotTableField
* pParentTableField
= maFields
.get( rBaseCacheField
.getParentGroupField() ).get() )
1357 pParentTableField
->finalizeParentGroupingImport( rxBaseDPField
, rBaseCacheField
, orItemNames
);
1360 Reference
< XDataPilotField
> PivotTable::getDataPilotField( const OUString
& rFieldName
) const
1362 Reference
< XDataPilotField
> xDPField
;
1363 if( !rFieldName
.isEmpty() && mxDPDescriptor
.is() ) try
1365 Reference
< XNameAccess
> xDPFieldsNA( mxDPDescriptor
->getDataPilotFields(), UNO_QUERY_THROW
);
1366 xDPField
.set( xDPFieldsNA
->getByName( rFieldName
), UNO_QUERY
);
1374 Reference
< XDataPilotField
> PivotTable::getDataPilotField( sal_Int32 nFieldIdx
) const
1376 Reference
< XDataPilotField
> xDPField
;
1377 if( const PivotTableField
* pTableField
= maFields
.get( nFieldIdx
).get() )
1378 xDPField
= getDataPilotField( pTableField
->getDPFieldName() );
1382 Reference
< XDataPilotField
> PivotTable::getDataLayoutField() const
1384 Reference
< XDataPilotField
> xDPField
;
1387 Reference
< XDataPilotDataLayoutFieldSupplier
> xDPDataFieldSupp( mxDPDescriptor
, UNO_QUERY_THROW
);
1388 xDPField
= xDPDataFieldSupp
->getDataLayoutField();
1396 PivotCacheField
* PivotTable::getCacheField( sal_Int32 nFieldIdx
)
1398 return mpPivotCache
? mpPivotCache
->getCacheField( nFieldIdx
) : nullptr;
1401 const PivotCacheField
* PivotTable::getCacheField( sal_Int32 nFieldIdx
) const
1403 return mpPivotCache
? mpPivotCache
->getCacheField( nFieldIdx
) : nullptr;
1406 const PivotCacheField
* PivotTable::getCacheFieldOfDataField( sal_Int32 nDataItemIdx
) const
1408 const PTDataFieldModel
* pDataField
= ContainerHelper::getVectorElement( maDataFields
, nDataItemIdx
);
1409 return pDataField
? getCacheField( pDataField
->mnField
) : nullptr;
1412 sal_Int32
PivotTable::getCacheDatabaseIndex( sal_Int32 nFieldIdx
) const
1414 return mpPivotCache
? mpPivotCache
->getCacheDatabaseIndex( nFieldIdx
) : -1;
1417 // private --------------------------------------------------------------------
1419 PivotTableField
* PivotTable::getTableField( sal_Int32 nFieldIdx
)
1421 return (nFieldIdx
== OOX_PT_DATALAYOUTFIELD
) ? &maDataField
: maFields
.get( nFieldIdx
).get();
1424 void PivotTable::importField( IndexVector
& orFields
, const AttributeList
& rAttribs
)
1426 orFields
.push_back( rAttribs
.getInteger( XML_x
, -1 ) );
1429 void PivotTable::importFields( IndexVector
& orFields
, SequenceInputStream
& rStrm
)
1431 OSL_ENSURE( orFields
.empty(), "PivotTable::importFields - multiple record instances" );
1433 sal_Int32 nCount
= rStrm
.readInt32();
1434 OSL_ENSURE( 4 * nCount
== rStrm
.getRemaining(), "PivotTable::importFields - invalid field count" );
1435 nCount
= static_cast< sal_Int32
>( rStrm
.getRemaining() / 4 );
1436 for( sal_Int32 nIdx
= 0; nIdx
< nCount
; ++nIdx
)
1437 orFields
.push_back( rStrm
.readInt32() );
1440 PivotTableBuffer::PivotTableBuffer( const WorkbookHelper
& rHelper
) :
1441 WorkbookHelper( rHelper
)
1445 PivotTable
& PivotTableBuffer::createPivotTable()
1447 PivotTableVector::value_type
xTable( new PivotTable( *this ) );
1448 maTables
.push_back( xTable
);
1452 void PivotTableBuffer::finalizeImport()
1454 maTables
.forEachMem( &PivotTable::finalizeImport
);
1460 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */