nss: upgrade to release 3.73
[LibreOffice.git] / sc / source / filter / oox / pivottablebuffer.cxx
blob6469f8da70bebf9ae04a57a00fcf72978044eafe
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
22 #include <set>
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>
54 #include <dpsave.hxx>
55 #include <dpdimsave.hxx>
56 #include <document.hxx>
57 #include <documentimport.hxx>
58 #include <workbooksettings.hxx>
60 namespace oox::xls {
62 using namespace ::com::sun::star::container;
63 using namespace ::com::sun::star::sheet;
64 using namespace ::com::sun::star::table;
65 using namespace ::com::sun::star::uno;
67 namespace {
69 const sal_Int32 OOX_PT_DATALAYOUTFIELD = -2; /// Placeholder index of data layout field.
71 const sal_Int32 OOX_PT_PREVIOUS_ITEM = 0x001000FC; /// Calculation of data item result is based on previous item.
72 const sal_Int32 OOX_PT_NEXT_ITEM = 0x001000FD; /// Calculation of data item result is based on next item.
74 const sal_uInt32 BIFF12_PTFIELD_DATAFIELD = 0x00000008;
75 const sal_uInt32 BIFF12_PTFIELD_DEFAULT = 0x00000100;
76 const sal_uInt32 BIFF12_PTFIELD_SUM = 0x00000200;
77 const sal_uInt32 BIFF12_PTFIELD_COUNTA = 0x00000400;
78 const sal_uInt32 BIFF12_PTFIELD_AVERAGE = 0x00000800;
79 const sal_uInt32 BIFF12_PTFIELD_MAX = 0x00001000;
80 const sal_uInt32 BIFF12_PTFIELD_MIN = 0x00002000;
81 const sal_uInt32 BIFF12_PTFIELD_PRODUCT = 0x00004000;
82 const sal_uInt32 BIFF12_PTFIELD_COUNT = 0x00008000;
83 const sal_uInt32 BIFF12_PTFIELD_STDDEV = 0x00010000;
84 const sal_uInt32 BIFF12_PTFIELD_STDDEVP = 0x00020000;
85 const sal_uInt32 BIFF12_PTFIELD_VAR = 0x00040000;
86 const sal_uInt32 BIFF12_PTFIELD_VARP = 0x00080000;
88 const sal_uInt32 BIFF12_PTFIELD_SHOWALL = 0x00000020;
89 const sal_uInt32 BIFF12_PTFIELD_OUTLINE = 0x00000040;
90 const sal_uInt32 BIFF12_PTFIELD_INSERTBLANKROW = 0x00000080;
91 const sal_uInt32 BIFF12_PTFIELD_SUBTOTALTOP = 0x00000100;
92 const sal_uInt32 BIFF12_PTFIELD_INSERTPAGEBREAK = 0x00000800;
93 const sal_uInt32 BIFF12_PTFIELD_AUTOSORT = 0x00001000;
94 const sal_uInt32 BIFF12_PTFIELD_SORTASCENDING = 0x00002000;
95 const sal_uInt32 BIFF12_PTFIELD_AUTOSHOW = 0x00004000;
96 const sal_uInt32 BIFF12_PTFIELD_AUTOSHOWTOP = 0x00008000;
97 const sal_uInt32 BIFF12_PTFIELD_MULTIPAGEITEMS = 0x00080000;
99 const sal_uInt16 BIFF12_PTFITEM_HIDDEN = 0x0001;
100 const sal_uInt16 BIFF12_PTFITEM_HIDEDETAILS = 0x0002;
102 const sal_uInt8 BIFF12_PTPAGEFIELD_HASNAME = 0x01;
103 const sal_Int32 BIFF12_PTPAGEFIELD_MULTIITEMS = 0x001000FE;
105 const sal_uInt16 BIFF12_PTFILTER_HASNAME = 0x0001;
106 const sal_uInt16 BIFF12_PTFILTER_HASDESCRIPTION = 0x0002;
107 const sal_uInt16 BIFF12_PTFILTER_HASSTRVALUE1 = 0x0004;
108 const sal_uInt16 BIFF12_PTFILTER_HASSTRVALUE2 = 0x0008;
110 const sal_uInt8 BIFF12_TOP10FILTER_TOP = 0x01;
111 const sal_uInt8 BIFF12_TOP10FILTER_PERCENT = 0x02;
113 const sal_uInt32 BIFF12_PTDEF_SHOWITEMS = 0x00000100;
114 const sal_uInt32 BIFF12_PTDEF_DISABLEFIELDLIST = 0x00000400;
115 const sal_uInt32 BIFF12_PTDEF_HIDECALCMEMBERS = 0x00001000;
116 const sal_uInt32 BIFF12_PTDEF_WITHHIDDENTOTALS = 0x00002000;
117 const sal_uInt32 BIFF12_PTDEF_HIDEDRILL = 0x00100000;
118 const sal_uInt32 BIFF12_PTDEF_PRINTDRILL = 0x00200000;
119 const sal_uInt32 BIFF12_PTDEF_HIDEHEADERS = 0x80000000;
121 const sal_uInt32 BIFF12_PTDEF_SHOWEMPTYROW = 0x00000004;
122 const sal_uInt32 BIFF12_PTDEF_SHOWEMPTYCOL = 0x00000008;
123 const sal_uInt32 BIFF12_PTDEF_ENABLEDRILL = 0x00000020;
124 const sal_uInt32 BIFF12_PTDEF_PRESERVEFORMATTING = 0x00000080;
125 const sal_uInt32 BIFF12_PTDEF_USEAUTOFORMAT = 0x00000100;
126 const sal_uInt32 BIFF12_PTDEF_SHOWERROR = 0x00000200;
127 const sal_uInt32 BIFF12_PTDEF_SHOWMISSING = 0x00000400;
128 const sal_uInt32 BIFF12_PTDEF_PAGEOVERTHENDOWN = 0x00000800;
129 const sal_uInt32 BIFF12_PTDEF_SUBTOTALHIDDENITEMS = 0x00001000;
130 const sal_uInt32 BIFF12_PTDEF_ROWGRANDTOTALS = 0x00002000;
131 const sal_uInt32 BIFF12_PTDEF_COLGRANDTOTALS = 0x00004000;
132 const sal_uInt32 BIFF12_PTDEF_FIELDPRINTTITLES = 0x00008000;
133 const sal_uInt32 BIFF12_PTDEF_ITEMPRINTTITLES = 0x00020000;
134 const sal_uInt32 BIFF12_PTDEF_MERGEITEM = 0x00040000;
135 const sal_uInt32 BIFF12_PTDEF_HASDATACAPTION = 0x00080000;
136 const sal_uInt32 BIFF12_PTDEF_HASGRANDTOTALCAPTION = 0x00100000;
137 const sal_uInt32 BIFF12_PTDEF_HASPAGESTYLE = 0x00200000;
138 const sal_uInt32 BIFF12_PTDEF_HASPIVOTTABLESTYLE = 0x00400000;
139 const sal_uInt32 BIFF12_PTDEF_HASVACATEDSTYLE = 0x00800000;
140 const sal_uInt32 BIFF12_PTDEF_APPLYNUMFMT = 0x01000000;
141 const sal_uInt32 BIFF12_PTDEF_APPLYFONT = 0x02000000;
142 const sal_uInt32 BIFF12_PTDEF_APPLYALIGNMENT = 0x04000000;
143 const sal_uInt32 BIFF12_PTDEF_APPLYBORDER = 0x08000000;
144 const sal_uInt32 BIFF12_PTDEF_APPLYFILL = 0x10000000;
145 const sal_uInt32 BIFF12_PTDEF_APPLYPROTECTION = 0x20000000;
146 const sal_uInt32 BIFF12_PTDEF_HASTAG = 0x40000000;
148 const sal_uInt32 BIFF12_PTDEF_NOERRORCAPTION = 0x00000040;
149 const sal_uInt32 BIFF12_PTDEF_NOMISSINGCAPTION = 0x00000080;
150 const sal_uInt32 BIFF12_PTDEF_HASROWHEADERCAPTION = 0x00000400;
151 const sal_uInt32 BIFF12_PTDEF_HASCOLHEADERCAPTION = 0x00000800;
152 const sal_uInt32 BIFF12_PTDEF_FIELDLISTSORTASC = 0x00001000;
153 const sal_uInt32 BIFF12_PTDEF_NOCUSTOMLISTSORT = 0x00004000;
155 const sal_uInt8 BIFF12_PTDEF_ROWAXIS = 1;
156 const sal_uInt8 BIFF12_PTDEF_COLAXIS = 2;
158 } // namespace
160 PTFieldItemModel::PTFieldItemModel() :
161 mnCacheItem( -1 ),
162 mnType( XML_data ),
163 mbShowDetails( true ),
164 mbHidden( false )
168 void PTFieldItemModel::setBiffType( sal_uInt16 nType )
170 static const sal_Int32 spnTypes[] = { XML_data, XML_default,
171 XML_sum, XML_countA, XML_avg, XML_max, XML_min, XML_product, XML_count,
172 XML_stdDev, XML_stdDevP, XML_var, XML_varP, XML_grand, XML_blank };
173 mnType = STATIC_ARRAY_SELECT( spnTypes, nType, XML_data );
176 PTFieldModel::PTFieldModel() :
177 mnAxis( XML_TOKEN_INVALID ),
178 mnNumFmtId( 0 ),
179 mnAutoShowItems( 10 ),
180 mnAutoShowRankBy( -1 ),
181 mnSortType( XML_manual ),
182 mnSortRefField( -1 ),
183 mnSortRefItem( -1 ),
184 mbDataField( false ),
185 mbDefaultSubtotal( true ),
186 mbSumSubtotal( false ),
187 mbCountASubtotal( false ),
188 mbAverageSubtotal( false ),
189 mbMaxSubtotal( false ),
190 mbMinSubtotal( false ),
191 mbProductSubtotal( false ),
192 mbCountSubtotal( false ),
193 mbStdDevSubtotal( false ),
194 mbStdDevPSubtotal( false ),
195 mbVarSubtotal( false ),
196 mbVarPSubtotal( false ),
197 mbShowAll( true ),
198 mbOutline( true ),
199 mbSubtotalTop( true ),
200 mbInsertBlankRow( false ),
201 mbInsertPageBreak( false ),
202 mbAutoShow( false ),
203 mbTopAutoShow( true ),
204 mbMultiPageItems( false )
208 void PTFieldModel::setBiffAxis( sal_uInt8 nAxis )
210 /* Weird. The axis field is organized as bit field, but only one of the
211 row/col/page flags are allowed at the same time and refer to the values
212 'axisRow', 'axisCol', and 'axisPage' of the XML attribute
213 'pivotField@axis'. Additionally, the fourth bit determines if the field
214 is a data field, which may appear combined with the row/col/page flags.
215 Therefore, this bit is unrelated to the 'axisValues' value of the
216 'pivotField@axis' attribute, but refers to the 'pivotField@dataField'
217 boolean attribute. */
218 static const sal_Int32 spnAxisIds[] = { XML_TOKEN_INVALID, XML_axisRow, XML_axisCol, XML_TOKEN_INVALID, XML_axisPage };
219 mnAxis = STATIC_ARRAY_SELECT( spnAxisIds, nAxis, XML_TOKEN_INVALID );
222 PTPageFieldModel::PTPageFieldModel() :
223 mnField( -1 ),
224 mnItem( BIFF12_PTPAGEFIELD_MULTIITEMS )
228 PTDataFieldModel::PTDataFieldModel() :
229 mnField( -1 ),
230 mnSubtotal( XML_sum ),
231 mnShowDataAs( XML_normal ),
232 mnBaseField( -1 ),
233 mnBaseItem( -1 ),
234 mnNumFmtId( 0 )
238 void PTDataFieldModel::setBiffSubtotal( sal_Int32 nSubtotal )
240 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 };
241 mnSubtotal = STATIC_ARRAY_SELECT( spnSubtotals, nSubtotal, XML_TOKEN_INVALID );
244 void PTDataFieldModel::setBiffShowDataAs( sal_Int32 nShowDataAs )
246 static const sal_Int32 spnShowDataAs[] = { XML_normal, XML_difference, XML_percent, XML_percentDiff, XML_runTotal, XML_percentOfRow, XML_percentOfCol, XML_percentOfTotal, XML_index };
247 mnShowDataAs = STATIC_ARRAY_SELECT( spnShowDataAs, nShowDataAs, XML_TOKEN_INVALID );
250 PivotTableField::PivotTableField( PivotTable& rPivotTable, sal_Int32 nFieldIndex ) :
251 WorkbookHelper( rPivotTable ),
252 mrPivotTable( rPivotTable ),
253 mnFieldIndex( nFieldIndex )
257 void PivotTableField::importPivotField( const AttributeList& rAttribs )
259 /* The documentation mentions a value 'axisValues' for the attribute
260 'pivotField@axis'. But this value is not used to mark a data field, as
261 data fields may be inserted in one of the row/column/page dimensions at
262 the same time. Therefore, the boolean attribute 'pivotField@dataField'
263 is really used to mark data fields. */
264 maModel.mnAxis = rAttribs.getToken( XML_axis, XML_TOKEN_INVALID );
265 maModel.mnNumFmtId = rAttribs.getInteger( XML_numFmtId, 0 );
266 maModel.mnAutoShowItems = rAttribs.getInteger( XML_itemPageCount, 10 );
267 maModel.mnAutoShowRankBy = rAttribs.getInteger( XML_rankBy, -1 );
268 maModel.mnSortType = rAttribs.getToken( XML_sortType, XML_manual );
269 maModel.mbDataField = rAttribs.getBool( XML_dataField, false );
270 maModel.mbDefaultSubtotal = rAttribs.getBool( XML_defaultSubtotal, true );
271 maModel.mbSumSubtotal = rAttribs.getBool( XML_sumSubtotal, false );
272 maModel.mbCountASubtotal = rAttribs.getBool( XML_countASubtotal, false );
273 maModel.mbAverageSubtotal = rAttribs.getBool( XML_avgSubtotal, false );
274 maModel.mbMaxSubtotal = rAttribs.getBool( XML_maxSubtotal, false );
275 maModel.mbMinSubtotal = rAttribs.getBool( XML_minSubtotal, false );
276 maModel.mbProductSubtotal = rAttribs.getBool( XML_productSubtotal, false );
277 maModel.mbCountSubtotal = rAttribs.getBool( XML_countSubtotal, false );
278 maModel.mbStdDevSubtotal = rAttribs.getBool( XML_stdDevSubtotal, false );
279 maModel.mbStdDevPSubtotal = rAttribs.getBool( XML_stdDevPSubtotal, false );
280 maModel.mbVarSubtotal = rAttribs.getBool( XML_varSubtotal, false );
281 maModel.mbVarPSubtotal = rAttribs.getBool( XML_varPSubtotal, false );
282 maModel.mbShowAll = rAttribs.getBool( XML_showAll, true );
283 maModel.mbOutline = rAttribs.getBool( XML_outline, true );
284 maModel.mbSubtotalTop = rAttribs.getBool( XML_subtotalTop, true );
285 maModel.mbInsertBlankRow = rAttribs.getBool( XML_insertBlankRow, false );
286 maModel.mbInsertPageBreak = rAttribs.getBool( XML_insertPageBreak, false );
287 maModel.mbAutoShow = rAttribs.getBool( XML_autoShow, false );
288 maModel.mbTopAutoShow = rAttribs.getBool( XML_topAutoShow, true );
289 maModel.mbMultiPageItems = rAttribs.getBool( XML_multipleItemSelectionAllowed, false );
292 void PivotTableField::importItem( const AttributeList& rAttribs )
294 PTFieldItemModel aModel;
295 aModel.mnCacheItem = rAttribs.getInteger( XML_x, -1 );
296 aModel.mnType = rAttribs.getToken( XML_t, XML_data );
297 aModel.mbShowDetails = rAttribs.getBool( XML_sd, true );
298 aModel.mbHidden = rAttribs.getBool( XML_h, false );
299 aModel.msCaption = rAttribs.getXString( XML_n, OUString() );
300 maItems.push_back( aModel );
303 void PivotTableField::importReference( const AttributeList& rAttribs )
305 // field index is stored as unsigned integer
306 maModel.mnSortRefField = static_cast< sal_Int32 >( rAttribs.getUnsigned( XML_field, SAL_MAX_UINT32 ) );
309 void PivotTableField::importReferenceItem( const AttributeList& rAttribs )
311 maModel.mnSortRefItem = rAttribs.getInteger( XML_v, -1 );
314 void PivotTableField::importPTField( SequenceInputStream& rStrm )
316 sal_uInt32 nFlags1, nFlags2;
317 nFlags1 = rStrm.readuInt32();
318 maModel.mnNumFmtId = rStrm.readInt32();
319 nFlags2 = rStrm.readuInt32();
320 maModel.mnAutoShowItems = rStrm.readInt32();
321 maModel.mnAutoShowRankBy = rStrm.readInt32();
323 maModel.setBiffAxis( extractValue< sal_uInt8 >( nFlags1, 0, 3 ) );
324 maModel.mbDataField = getFlag( nFlags1, BIFF12_PTFIELD_DATAFIELD );
325 maModel.mbDefaultSubtotal = getFlag( nFlags1, BIFF12_PTFIELD_DEFAULT );
326 maModel.mbSumSubtotal = getFlag( nFlags1, BIFF12_PTFIELD_SUM );
327 maModel.mbCountASubtotal = getFlag( nFlags1, BIFF12_PTFIELD_COUNTA );
328 maModel.mbAverageSubtotal = getFlag( nFlags1, BIFF12_PTFIELD_AVERAGE );
329 maModel.mbMaxSubtotal = getFlag( nFlags1, BIFF12_PTFIELD_MAX );
330 maModel.mbMinSubtotal = getFlag( nFlags1, BIFF12_PTFIELD_MIN );
331 maModel.mbProductSubtotal = getFlag( nFlags1, BIFF12_PTFIELD_PRODUCT );
332 maModel.mbCountSubtotal = getFlag( nFlags1, BIFF12_PTFIELD_COUNT );
333 maModel.mbStdDevSubtotal = getFlag( nFlags1, BIFF12_PTFIELD_STDDEV );
334 maModel.mbStdDevPSubtotal = getFlag( nFlags1, BIFF12_PTFIELD_STDDEVP );
335 maModel.mbVarSubtotal = getFlag( nFlags1, BIFF12_PTFIELD_VAR );
336 maModel.mbVarPSubtotal = getFlag( nFlags1, BIFF12_PTFIELD_VARP );
338 maModel.mbShowAll = getFlag( nFlags2, BIFF12_PTFIELD_SHOWALL );
339 maModel.mbOutline = getFlag( nFlags2, BIFF12_PTFIELD_OUTLINE );
340 maModel.mbSubtotalTop = getFlag( nFlags2, BIFF12_PTFIELD_SUBTOTALTOP );
341 maModel.mbInsertBlankRow = getFlag( nFlags2, BIFF12_PTFIELD_INSERTBLANKROW );
342 maModel.mbInsertPageBreak = getFlag( nFlags2, BIFF12_PTFIELD_INSERTPAGEBREAK );
343 maModel.mbAutoShow = getFlag( nFlags2, BIFF12_PTFIELD_AUTOSHOW );
344 maModel.mbTopAutoShow = getFlag( nFlags2, BIFF12_PTFIELD_AUTOSHOWTOP );
345 maModel.mbMultiPageItems = getFlag( nFlags2, BIFF12_PTFIELD_MULTIPAGEITEMS );
347 bool bAutoSort = getFlag( nFlags2, BIFF12_PTFIELD_AUTOSORT );
348 bool bAscending = getFlag( nFlags2, BIFF12_PTFIELD_SORTASCENDING );
349 maModel.mnSortType = bAutoSort ? (bAscending ? XML_ascending : XML_descending) : XML_manual;
352 void PivotTableField::importPTFItem( SequenceInputStream& rStrm )
354 PTFieldItemModel aModel;
355 sal_uInt8 nType;
356 sal_uInt16 nFlags;
357 nType = rStrm.readuChar();
358 nFlags = rStrm.readuInt16();
359 aModel.mnCacheItem = rStrm.readInt32();
361 aModel.setBiffType( nType );
362 aModel.mbShowDetails = !getFlag( nFlags, BIFF12_PTFITEM_HIDEDETAILS );
363 aModel.mbHidden = getFlag( nFlags, BIFF12_PTFITEM_HIDDEN );
365 maItems.push_back( aModel );
368 void PivotTableField::importPTReference( SequenceInputStream& rStrm )
370 maModel.mnSortRefField = rStrm.readInt32();
373 void PivotTableField::importPTReferenceItem( SequenceInputStream& rStrm )
375 maModel.mnSortRefItem = rStrm.readInt32();
378 void PivotTableField::finalizeImport( const Reference< XDataPilotDescriptor >& rxDPDesc )
380 /* Process all fields based on source data, other fields (e.g. group
381 fields) are processed from here. PivotCache::getCacheDatabaseIndex()
382 returns -1 for all fields not based on source data. */
383 Reference< XDataPilotField > xDPField;
384 sal_Int32 nDatabaseIdx = mrPivotTable.getCacheDatabaseIndex( mnFieldIndex );
385 if( !((nDatabaseIdx >= 0) && rxDPDesc.is()) )
386 return;
390 // try to get the source field and its name from passed DataPilot descriptor
391 Reference< XIndexAccess > xDPFieldsIA( rxDPDesc->getDataPilotFields(), UNO_SET_THROW );
392 xDPField.set( xDPFieldsIA->getByIndex( nDatabaseIdx ), UNO_QUERY_THROW );
393 Reference< XNamed > xDPFieldName( xDPField, UNO_QUERY_THROW );
394 maDPFieldName = xDPFieldName->getName();
395 OSL_ENSURE( !maDPFieldName.isEmpty(), "PivotTableField::finalizeImport - no field name in source data found" );
397 // try to convert grouping settings
398 if( const PivotCacheField* pCacheField = mrPivotTable.getCacheField( mnFieldIndex ) )
400 // numeric grouping is done inplace, no nested group fields will appear
401 if( pCacheField->hasNumericGrouping() )
403 pCacheField->convertNumericGrouping( xDPField );
405 else if( pCacheField->hasDateGrouping() )
407 // first date group settings are inplace
408 pCacheField->createDateGroupField( xDPField );
409 // create all nested group fields (if any)
410 mrPivotTable.finalizeDateGroupingImport( xDPField, mnFieldIndex );
412 else if( pCacheField->hasParentGrouping() )
415 // create a list of all item names, needed to map between original and group items
416 ::std::vector< OUString > aItems;
417 pCacheField->getCacheItemNames( aItems );
418 PivotCacheGroupItemVector aItemNames;
419 for( const auto& rItem : aItems )
420 aItemNames.emplace_back( rItem );
421 // create all nested group fields (if any)
422 mrPivotTable.finalizeParentGroupingImport( xDPField, *pCacheField, aItemNames );
426 catch( Exception& )
431 void PivotTableField::finalizeDateGroupingImport( const Reference< XDataPilotField >& rxBaseDPField, sal_Int32 nBaseFieldIdx )
433 if( maDPFieldName.isEmpty() ) // prevent endless loops if file format is broken
435 if( PivotCacheField* pCacheField = mrPivotTable.getCacheField( mnFieldIndex ) )
437 if( !pCacheField->isDatabaseField() && pCacheField->hasDateGrouping() && (pCacheField->getGroupBaseField() == nBaseFieldIdx) )
439 maDPFieldName = pCacheField->createDateGroupField( rxBaseDPField );
440 pCacheField->setFinalGroupName(maDPFieldName);
441 OSL_ENSURE( !maDPFieldName.isEmpty(), "PivotTableField::finalizeDateGroupingImport - cannot create date group field" );
447 void PivotTableField::finalizeParentGroupingImport( const Reference< XDataPilotField >& rxBaseDPField, const PivotCacheField& rBaseCacheField, PivotCacheGroupItemVector& orItemNames )
449 if( !maDPFieldName.isEmpty() ) // prevent endless loops if file format is broken
450 return;
452 PivotCacheField* pCacheField = mrPivotTable.getCacheField( mnFieldIndex );
453 if( !pCacheField )
454 return;
456 // data field can have user defined groupname captions, apply them
457 // if they do
458 IdCaptionPairList captionList;
459 for( const auto& rItem : maItems )
461 if ( rItem.mnType == XML_data && rItem.msCaption.getLength() )
462 captionList.emplace_back( rItem.mnCacheItem, rItem.msCaption );
464 if ( !captionList.empty() )
465 pCacheField->applyItemCaptions( captionList );
467 maDPFieldName = pCacheField->createParentGroupField( rxBaseDPField, rBaseCacheField, orItemNames );
468 pCacheField->setFinalGroupName(maDPFieldName);
469 // on success, try to create nested group fields
470 Reference< XDataPilotField > xDPField = mrPivotTable.getDataPilotField( maDPFieldName );
471 if( xDPField.is() )
472 mrPivotTable.finalizeParentGroupingImport( xDPField, *pCacheField, orItemNames );
475 void PivotTableField::finalizeImportBasedOnCache( const Reference< XDataPilotDescriptor >& rxDPDesc)
477 /* Process all fields based on source data, other fields (e.g. group
478 fields) are processed based on cache fields.*/
479 Reference< XDataPilotField > xDPField;
480 sal_Int32 nDatabaseIdx = mrPivotTable.getCacheDatabaseIndex( mnFieldIndex );
481 if( (nDatabaseIdx >= 0) && rxDPDesc.is() ) try
483 // Try to get the source field and its name from passed DataPilot descriptor
484 Reference< XIndexAccess > xDPFieldsIA( rxDPDesc->getDataPilotFields(), UNO_SET_THROW );
485 xDPField.set( xDPFieldsIA->getByIndex( nDatabaseIdx ), UNO_QUERY_THROW );
486 Reference< XNamed > xDPFieldName( xDPField, UNO_QUERY_THROW );
487 maDPFieldName = xDPFieldName->getName();
488 SAL_WARN_IF( maDPFieldName.isEmpty(), "sc.filter", "PivotTableField::finalizeImportBasedOnCache - no field name in source data found" );
490 catch( Exception& )
494 // Use group names already generated for another table using the same group field.
495 if( const PivotCacheField* pCacheField = mrPivotTable.getCacheField( mnFieldIndex ) )
497 if(!pCacheField->getFinalGroupName().isEmpty())
498 maDPFieldName = pCacheField->getFinalGroupName();
502 void PivotTableField::convertRowField()
504 convertRowColPageField( XML_axisRow );
507 void PivotTableField::convertColField()
509 convertRowColPageField( XML_axisCol );
512 void PivotTableField::convertHiddenField()
514 convertRowColPageField( XML_TOKEN_INVALID );
517 void PivotTableField::convertPageField( const PTPageFieldModel& rPageField )
519 OSL_ENSURE( rPageField.mnField == mnFieldIndex, "PivotTableField::convertPageField - wrong field index" );
520 // convert all settings common for row/column/page fields
521 Reference< XDataPilotField > xDPField = convertRowColPageField( XML_axisPage );
523 if( !xDPField.is() )
524 return;
526 PropertySet aPropSet( xDPField );
528 // find cache item used as 'selected page'
529 sal_Int32 nCacheItem = -1;
530 if( maModel.mbMultiPageItems )
532 // multiple items may be selected
533 OSL_ENSURE( rPageField.mnItem == BIFF12_PTPAGEFIELD_MULTIITEMS, "PivotTableField::convertPageField - unexpected cache item index" );
534 // try to find a single visible item
535 bool bHasMultiItems = false;
536 for( const auto& rItem : maItems )
538 if( (rItem.mnType == XML_data) && !rItem.mbHidden )
540 bHasMultiItems = nCacheItem >= 0;
541 nCacheItem = bHasMultiItems ? -1 : rItem.mnCacheItem;
544 if( bHasMultiItems )
545 break;
548 else
550 // single item may be selected
551 if( (0 <= rPageField.mnItem) && (rPageField.mnItem < static_cast< sal_Int32 >( maItems.size() )) )
552 nCacheItem = maItems[ rPageField.mnItem ].mnCacheItem;
555 if( nCacheItem < 0 )
556 return;
558 if( const PivotCacheField* pCacheField = mrPivotTable.getCacheField( mnFieldIndex ) )
560 if( const PivotCacheItem* pSharedItem = pCacheField->getCacheItem( nCacheItem ) )
562 ScDPObject* pDPObj = mrPivotTable.getDPObject();
563 ScDPSaveData* pSaveData = pDPObj->GetSaveData();
564 ScDPSaveDimension* pDim = pSaveData->GetDimensionByName(pCacheField->getName());
565 OUString aSelectedPage = pSharedItem->getFormattedName(*pDim, pDPObj, DateTime(getWorkbookSettings().getNullDate()));
566 aPropSet.setProperty( PROP_SelectedPage, aSelectedPage );
571 void PivotTableField::convertDataField( const PTDataFieldModel& rDataField )
573 OSL_ENSURE( rDataField.mnField == mnFieldIndex, "PivotTableField::convertDataField - wrong field index" );
574 OSL_ENSURE( maModel.mbDataField, "PivotTableField::convertDataField - not a data field" );
575 Reference< XDataPilotField > xDPField = mrPivotTable.getDataPilotField( maDPFieldName );
576 if( !xDPField.is() )
577 return;
579 PropertySet aPropSet( xDPField );
581 // field orientation
582 aPropSet.setProperty( PROP_Orientation, DataPilotFieldOrientation_DATA );
584 if (!rDataField.maName.isEmpty())
585 aPropSet.setProperty(PROP_Name, rDataField.maName);
587 /* Field aggregation function. Documentation is a little bit confused
588 about which names to use for the count functions. The name 'count'
589 means 'count all', and 'countNum' means 'count numbers'. On the
590 other hand, for subtotals, 'countA' means 'count all', and 'count'
591 means 'count numbers' (see above). */
592 GeneralFunction eAggFunc = GeneralFunction_SUM;
593 switch( rDataField.mnSubtotal )
595 case XML_sum: eAggFunc = GeneralFunction_SUM; break;
596 case XML_count: eAggFunc = GeneralFunction_COUNT; break;
597 case XML_average: eAggFunc = GeneralFunction_AVERAGE; break;
598 case XML_max: eAggFunc = GeneralFunction_MAX; break;
599 case XML_min: eAggFunc = GeneralFunction_MIN; break;
600 case XML_product: eAggFunc = GeneralFunction_PRODUCT; break;
601 case XML_countNums: eAggFunc = GeneralFunction_COUNTNUMS; break;
602 case XML_stdDev: eAggFunc = GeneralFunction_STDEV; break;
603 case XML_stdDevp: eAggFunc = GeneralFunction_STDEVP; break;
604 case XML_var: eAggFunc = GeneralFunction_VAR; break;
605 case XML_varp: eAggFunc = GeneralFunction_VARP; break;
606 default: OSL_FAIL( "PivotTableField::convertDataField - unknown aggregation function" );
608 aPropSet.setProperty( PROP_Function, eAggFunc );
610 // field reference ('show data as')
611 DataPilotFieldReference aReference;
612 aReference.ReferenceType = DataPilotFieldReferenceType::NONE;
613 switch( rDataField.mnShowDataAs )
615 case XML_difference: aReference.ReferenceType = DataPilotFieldReferenceType::ITEM_DIFFERENCE; break;
616 case XML_percent: aReference.ReferenceType = DataPilotFieldReferenceType::ITEM_PERCENTAGE; break;
617 case XML_percentDiff: aReference.ReferenceType = DataPilotFieldReferenceType::ITEM_PERCENTAGE_DIFFERENCE; break;
618 case XML_runTotal: aReference.ReferenceType = DataPilotFieldReferenceType::RUNNING_TOTAL; break;
619 case XML_percentOfRow: aReference.ReferenceType = DataPilotFieldReferenceType::ROW_PERCENTAGE; break;
620 case XML_percentOfCol: aReference.ReferenceType = DataPilotFieldReferenceType::COLUMN_PERCENTAGE; break;
621 case XML_percentOfTotal: aReference.ReferenceType = DataPilotFieldReferenceType::TOTAL_PERCENTAGE; break;
622 case XML_index: aReference.ReferenceType = DataPilotFieldReferenceType::INDEX; break;
624 if( aReference.ReferenceType == DataPilotFieldReferenceType::NONE )
625 return;
627 const PivotCacheField* pCacheField = mrPivotTable.getCacheField( rDataField.mnBaseField );
628 if( !pCacheField )
629 return;
631 aReference.ReferenceField = pCacheField->getName();
632 switch( rDataField.mnBaseItem )
634 case OOX_PT_PREVIOUS_ITEM:
635 aReference.ReferenceItemType = DataPilotFieldReferenceItemType::PREVIOUS;
636 break;
637 case OOX_PT_NEXT_ITEM:
638 aReference.ReferenceItemType = DataPilotFieldReferenceItemType::NEXT;
639 break;
640 default:
641 aReference.ReferenceItemType = DataPilotFieldReferenceItemType::NAMED;
642 if( const PivotCacheItem* pCacheItem = pCacheField->getCacheItem( rDataField.mnBaseItem ) )
643 aReference.ReferenceItemName = pCacheItem->getName();
645 aPropSet.setProperty( PROP_Reference, aReference );
648 // private --------------------------------------------------------------------
650 Reference< XDataPilotField > PivotTableField::convertRowColPageField( sal_Int32 nAxis )
652 bool bDataLayout = mnFieldIndex == OOX_PT_DATALAYOUTFIELD;
653 Reference< XDataPilotField > xDPField = bDataLayout ? mrPivotTable.getDataLayoutField() : mrPivotTable.getDataPilotField( maDPFieldName );
654 OSL_ENSURE( bDataLayout || (nAxis == maModel.mnAxis), "PivotTableField::convertRowColPageField - field axis mismatch" );
656 if( xDPField.is() )
658 // TODO: Use this to set properties directly, bypassing the slow uno layer.
659 ScDPObject* pDPObj = mrPivotTable.getDPObject();
661 PropertySet aPropSet( xDPField );
663 // field orientation
664 DataPilotFieldOrientation eFieldOrient = DataPilotFieldOrientation_HIDDEN;
665 switch( nAxis )
667 case XML_axisRow: eFieldOrient = DataPilotFieldOrientation_ROW; break;
668 case XML_axisCol: eFieldOrient = DataPilotFieldOrientation_COLUMN; break;
669 case XML_axisPage: eFieldOrient = DataPilotFieldOrientation_PAGE; break;
671 if( eFieldOrient != DataPilotFieldOrientation_HIDDEN )
672 aPropSet.setProperty( PROP_Orientation, eFieldOrient );
674 // all other settings not for the data layout field
675 if( !bDataLayout )
677 /* Field subtotal functions. Ignore the 'defaultSubtotal' flag, if
678 explicit functions are set. This is different behaviour between
679 XML (where 'defaultSubtotal' is set regardless of other
680 functions) and binary formats (where 'defaultSubtotal' is not
681 set if other functions are set). */
682 ::std::vector< GeneralFunction > aSubtotals;
683 /* Order of subtotals is fixed in Excel. Documentation is a little
684 bit confused about which names to use for the count functions.
685 For subtotals, 'countA' means 'count all', and 'count' means
686 'count numbers'. On the other hand, for the data field
687 aggregation function, 'count' means 'count all', and 'countNum'
688 means 'count numbers' (see below). */
689 if( maModel.mbSumSubtotal ) aSubtotals.push_back( GeneralFunction_SUM );
690 if( maModel.mbCountASubtotal ) aSubtotals.push_back( GeneralFunction_COUNT );
691 if( maModel.mbAverageSubtotal ) aSubtotals.push_back( GeneralFunction_AVERAGE );
692 if( maModel.mbMaxSubtotal ) aSubtotals.push_back( GeneralFunction_MAX );
693 if( maModel.mbMinSubtotal ) aSubtotals.push_back( GeneralFunction_MIN );
694 if( maModel.mbProductSubtotal ) aSubtotals.push_back( GeneralFunction_PRODUCT );
695 if( maModel.mbCountSubtotal ) aSubtotals.push_back( GeneralFunction_COUNTNUMS );
696 if( maModel.mbStdDevSubtotal ) aSubtotals.push_back( GeneralFunction_STDEV );
697 if( maModel.mbStdDevPSubtotal ) aSubtotals.push_back( GeneralFunction_STDEVP );
698 if( maModel.mbVarSubtotal ) aSubtotals.push_back( GeneralFunction_VAR );
699 if( maModel.mbVarPSubtotal ) aSubtotals.push_back( GeneralFunction_VARP );
700 // if no function is set manually, check the 'defaultSubtotal' flag
701 if( aSubtotals.empty() && maModel.mbDefaultSubtotal )
702 aSubtotals.push_back( GeneralFunction_AUTO );
703 aPropSet.setProperty( PROP_Subtotals, ContainerHelper::vectorToSequence( aSubtotals ) );
705 // layout settings
706 DataPilotFieldLayoutInfo aLayoutInfo;
707 aLayoutInfo.LayoutMode = maModel.mbOutline ?
708 (maModel.mbSubtotalTop ? DataPilotFieldLayoutMode::OUTLINE_SUBTOTALS_TOP : DataPilotFieldLayoutMode::OUTLINE_SUBTOTALS_BOTTOM) :
709 DataPilotFieldLayoutMode::TABULAR_LAYOUT;
710 aLayoutInfo.AddEmptyLines = maModel.mbInsertBlankRow;
711 aPropSet.setProperty( PROP_LayoutInfo, aLayoutInfo );
712 aPropSet.setProperty( PROP_ShowEmpty, maModel.mbShowAll );
714 // auto show (OOXML/BIFF12 only)
715 if( maModel.mbAutoShow )
717 DataPilotFieldAutoShowInfo aAutoShowInfo;
718 aAutoShowInfo.IsEnabled = true;
719 aAutoShowInfo.ShowItemsMode = maModel.mbTopAutoShow ? DataPilotFieldShowItemsMode::FROM_TOP : DataPilotFieldShowItemsMode::FROM_BOTTOM;
720 aAutoShowInfo.ItemCount = maModel.mnAutoShowItems;
721 if( const PivotCacheField* pCacheField = mrPivotTable.getCacheFieldOfDataField( maModel.mnAutoShowRankBy ) )
722 aAutoShowInfo.DataField = pCacheField->getName();
723 aPropSet.setProperty( PROP_AutoShowInfo, aAutoShowInfo );
726 // auto sort
727 DataPilotFieldSortInfo aSortInfo;
728 aSortInfo.IsAscending = maModel.mnSortType == XML_ascending;
729 if( (maModel.mnSortType != XML_ascending) && (maModel.mnSortType != XML_descending) )
731 aSortInfo.Mode = DataPilotFieldSortMode::MANUAL;
733 else
735 const PivotCacheField* pCacheField = (maModel.mnSortRefField == OOX_PT_DATALAYOUTFIELD) ?
736 mrPivotTable.getCacheFieldOfDataField( maModel.mnSortRefItem ) : nullptr;
737 if( pCacheField )
739 aSortInfo.Mode = DataPilotFieldSortMode::DATA;
740 aSortInfo.Field = pCacheField->getName();
742 else
744 aSortInfo.Mode = DataPilotFieldSortMode::NAME;
747 aPropSet.setProperty( PROP_SortInfo, aSortInfo );
749 // item settings
750 if (const PivotCacheField* pCacheField = mrPivotTable.getCacheField(mnFieldIndex))
752 ScDPSaveData* pSaveData = pDPObj->GetSaveData();
753 ScDPSaveDimension* pDim = pSaveData->GetDimensionByName(pCacheField->getName());
757 for( const auto& rItem : maItems )
759 if (rItem.mnType != XML_data)
760 continue;
762 const PivotCacheItem* pSharedItem = pCacheField->getCacheItem(rItem.mnCacheItem);
763 if (!pSharedItem)
764 continue;
768 ScDPSaveMember* pMem = pDim->GetMemberByName(pSharedItem->getFormattedName(*pDim, pDPObj, DateTime(getWorkbookSettings().getNullDate())));
769 pMem->SetShowDetails(rItem.mbShowDetails);
770 pMem->SetIsVisible(!rItem.mbHidden);
772 catch( Exception& )
774 // catch every failed container access to be able to process following items
778 catch (const Exception&) {}
782 return xDPField;
785 PTFilterModel::PTFilterModel() :
786 mfValue( 0.0 ),
787 mnField( -1 ),
788 mnMemPropField( -1 ),
789 mnType( XML_TOKEN_INVALID ),
790 mnEvalOrder( 0 ),
791 mnId( -1 ),
792 mnMeasureField( -1 ),
793 mnMeasureHier( -1 ),
794 mbTopFilter( true )
798 PivotTableFilter::PivotTableFilter( const PivotTable& rPivotTable ) :
799 WorkbookHelper( rPivotTable ),
800 mrPivotTable( rPivotTable )
804 void PivotTableFilter::importFilter( const AttributeList& rAttribs )
806 maModel.maName = rAttribs.getXString( XML_name, OUString() );
807 maModel.maDescription = rAttribs.getXString( XML_description, OUString() );
808 maModel.maStrValue1 = rAttribs.getXString( XML_stringValue1, OUString() );
809 maModel.maStrValue2 = rAttribs.getXString( XML_stringValue2, OUString() );
810 maModel.mnField = rAttribs.getInteger( XML_fld, -1 );
811 maModel.mnMemPropField = rAttribs.getInteger( XML_mpFld, -1 );
812 maModel.mnType = rAttribs.getToken( XML_type, XML_TOKEN_INVALID );
813 maModel.mnEvalOrder = rAttribs.getInteger( XML_evalOrder, 0 );
814 maModel.mnId = rAttribs.getInteger( XML_id, -1 );
815 maModel.mnMeasureField = rAttribs.getInteger( XML_iMeasureFld, -1 );
816 maModel.mnMeasureHier = rAttribs.getInteger( XML_iMeasureHier, -1 );
819 void PivotTableFilter::importTop10( const AttributeList& rAttribs )
821 OSL_ENSURE( rAttribs.getBool( XML_percent, false ) == (maModel.mnType == XML_percent),
822 "PivotTableFilter::importTop10 - unexpected value of percent attribute" );
823 maModel.mfValue = rAttribs.getDouble( XML_val, 0.0 );
824 maModel.mbTopFilter = rAttribs.getBool( XML_top, true );
827 void PivotTableFilter::importPTFilter( SequenceInputStream& rStrm )
829 sal_Int32 nType;
830 sal_uInt16 nFlags;
831 maModel.mnField = rStrm.readInt32();
832 maModel.mnMemPropField = rStrm.readInt32();
833 nType = rStrm.readInt32();
834 rStrm.skip( 4 ); // unused
835 maModel.mnId = rStrm.readInt32();
836 maModel.mnMeasureField = rStrm.readInt32();
837 maModel.mnMeasureHier = rStrm.readInt32();
838 nFlags = rStrm.readuInt16();
839 if( getFlag( nFlags, BIFF12_PTFILTER_HASNAME ) )
840 rStrm >> maModel.maName;
841 if( getFlag( nFlags, BIFF12_PTFILTER_HASDESCRIPTION ) )
842 rStrm >> maModel.maDescription;
843 if( getFlag( nFlags, BIFF12_PTFILTER_HASSTRVALUE1 ) )
844 rStrm >> maModel.maStrValue1;
845 if( getFlag( nFlags, BIFF12_PTFILTER_HASSTRVALUE2 ) )
846 rStrm >> maModel.maStrValue2;
848 static const sal_Int32 spnTypes[] =
850 XML_unknown,
851 // data field top10 filter (1-3)
852 XML_count, XML_percent, XML_sum,
853 // caption filter (4-17)
854 XML_captionEqual, XML_captionNotEqual,
855 XML_captionBeginsWith, XML_captionNotBeginsWith, XML_captionEndsWith, XML_captionNotEndsWith,
856 XML_captionContains, XML_captionNotContains, XML_captionGreaterThan, XML_captionGreaterThanOrEqual,
857 XML_captionLessThan, XML_captionLessThanOrEqual, XML_captionBetween, XML_captionNotBetween,
858 // value filter (18-25)
859 XML_valueEqual, XML_valueNotEqual, XML_valueGreaterThan, XML_valueGreaterThanOrEqual,
860 XML_valueLessThan, XML_valueLessThanOrEqual, XML_valueBetween, XML_valueNotBetween,
861 // date filter (26-65)
862 XML_dateEqual, XML_dateOlderThan, XML_dateNewerThan, XML_dateBetween,
863 XML_tomorrow, XML_today, XML_yesterday, XML_nextWeek, XML_thisWeek, XML_lastWeek,
864 XML_nextMonth, XML_thisMonth, XML_lastMonth, XML_nextQuarter, XML_thisQuarter, XML_lastQuarter,
865 XML_nextYear, XML_thisYear, XML_lastYear, XML_yearToDate, XML_Q1, XML_Q2, XML_Q3, XML_Q4,
866 XML_M1, XML_M2, XML_M3, XML_M4, XML_M5, XML_M6, XML_M7, XML_M8, XML_M9, XML_M10, XML_M11, XML_M12,
867 XML_dateNotEqual, XML_dateOlderThanOrEqual, XML_dateNewerThanOrEqual, XML_dateNotBetween
869 maModel.mnType = STATIC_ARRAY_SELECT( spnTypes, nType, XML_TOKEN_INVALID );
872 void PivotTableFilter::importTop10Filter( SequenceInputStream& rStrm )
874 sal_uInt8 nFlags;
875 nFlags = rStrm.readuChar();
876 maModel.mfValue = rStrm.readDouble();
878 SAL_WARN_IF(
879 getFlag(nFlags, BIFF12_TOP10FILTER_PERCENT) != (maModel.mnType == XML_percent),
880 "sc.filter",
881 "PivotTableFilter::importTop10 - unexpected value of percent attribute");
882 maModel.mbTopFilter = getFlag( nFlags, BIFF12_TOP10FILTER_TOP );
885 void PivotTableFilter::finalizeImport()
887 // only simple top10 filter supported
888 if( maModel.mnType != XML_count )
889 return;
891 PropertySet aPropSet( mrPivotTable.getDataPilotField( maModel.mnField ) );
892 if( aPropSet.is() )
894 DataPilotFieldAutoShowInfo aAutoShowInfo;
895 aAutoShowInfo.IsEnabled = true;
896 aAutoShowInfo.ShowItemsMode = maModel.mbTopFilter ? DataPilotFieldShowItemsMode::FROM_TOP : DataPilotFieldShowItemsMode::FROM_BOTTOM;
897 aAutoShowInfo.ItemCount = getLimitedValue< sal_Int32, double >( maModel.mfValue, 0, SAL_MAX_INT32 );
898 if( const PivotCacheField* pCacheField = mrPivotTable.getCacheFieldOfDataField( maModel.mnMeasureField ) )
899 aAutoShowInfo.DataField = pCacheField->getName();
900 aPropSet.setProperty( PROP_AutoShowInfo, aAutoShowInfo );
904 PTDefinitionModel::PTDefinitionModel() :
905 mnCacheId( -1 ),
906 mnDataPosition( 0 ),
907 mnPageWrap( 0 ),
908 mnIndent( 1 ),
909 mnChartFormat( 0 ),
910 mbDataOnRows( false ),
911 mbShowError( false ),
912 mbShowMissing( true ),
913 mbShowItems( true ),
914 mbDisableFieldList( false ),
915 mbShowCalcMembers( true ),
916 mbVisualTotals( true ),
917 mbShowDrill( true ),
918 mbPrintDrill( false ),
919 mbEnableDrill( true ),
920 mbPreserveFormatting( true ),
921 mbUseAutoFormat( false ),
922 mbPageOverThenDown( false ),
923 mbSubtotalHiddenItems( false ),
924 mbRowGrandTotals( true ),
925 mbColGrandTotals( true ),
926 mbFieldPrintTitles( false ),
927 mbItemPrintTitles( false ),
928 mbMergeItem( false ),
929 mbShowEmptyRow( false ),
930 mbShowEmptyCol( false ),
931 mbShowHeaders( true ),
932 mbFieldListSortAsc( false ),
933 mbCustomListSort( true )
937 PTLocationModel::PTLocationModel() :
938 mnFirstHeaderRow( 0 ),
939 mnFirstDataRow( 0 ),
940 mnFirstDataCol( 0 ),
941 mnRowPageCount( 0 ),
942 mnColPageCount( 0 )
946 PivotTable::PivotTable( const WorkbookHelper& rHelper ) :
947 WorkbookHelper( rHelper ),
948 mpDPObject(nullptr),
949 maDataField( *this, OOX_PT_DATALAYOUTFIELD ),
950 mpPivotCache( nullptr )
954 void PivotTable::importPivotTableDefinition( const AttributeList& rAttribs )
956 maDefModel.maName = rAttribs.getXString( XML_name, OUString() );
957 maDefModel.maDataCaption = rAttribs.getXString( XML_dataCaption , OUString() );
958 maDefModel.maGrandTotalCaption = rAttribs.getXString( XML_grandTotalCaption, OUString() );
959 maDefModel.maRowHeaderCaption = rAttribs.getXString( XML_rowHeaderCaption, OUString() );
960 maDefModel.maColHeaderCaption = rAttribs.getXString( XML_colHeaderCaption, OUString() );
961 maDefModel.maErrorCaption = rAttribs.getXString( XML_errorCaption, OUString() );
962 maDefModel.maMissingCaption = rAttribs.getXString( XML_missingCaption, OUString() );
963 maDefModel.maPageStyle = rAttribs.getXString( XML_pageStyle, OUString() );
964 maDefModel.maPivotTableStyle = rAttribs.getXString( XML_pivotTableStyle, OUString() );
965 maDefModel.maVacatedStyle = rAttribs.getXString( XML_vacatedStyle, OUString() );
966 maDefModel.maTag = rAttribs.getXString( XML_tag, OUString() );
967 maDefModel.mnCacheId = rAttribs.getInteger( XML_cacheId, -1 );
968 maDefModel.mnDataPosition = rAttribs.getInteger( XML_dataPosition, 0 );
969 maDefModel.mnPageWrap = rAttribs.getInteger( XML_pageWrap, 0 );
970 maDefModel.mnIndent = rAttribs.getInteger( XML_indent, 1 );
971 maDefModel.mnChartFormat = rAttribs.getInteger( XML_chartFormat, 0 );
972 maDefModel.mnAutoFormatId = rAttribs.getInteger( XML_autoFormatId, 0 );
973 maDefModel.mbDataOnRows = rAttribs.getBool( XML_dataOnRows, false );
974 maDefModel.mbShowError = rAttribs.getBool( XML_showError, false );
975 maDefModel.mbShowMissing = rAttribs.getBool( XML_showMissing, true );
976 maDefModel.mbShowItems = rAttribs.getBool( XML_showItems, true );
977 maDefModel.mbDisableFieldList = rAttribs.getBool( XML_disableFieldList, false );
978 maDefModel.mbShowCalcMembers = rAttribs.getBool( XML_showCalcMbrs, true );
979 maDefModel.mbVisualTotals = rAttribs.getBool( XML_visualTotals, true );
980 maDefModel.mbShowDrill = rAttribs.getBool( XML_showDrill, true );
981 maDefModel.mbPrintDrill = rAttribs.getBool( XML_printDrill, false );
982 maDefModel.mbEnableDrill = rAttribs.getBool( XML_enableDrill, true );
983 maDefModel.mbPreserveFormatting = rAttribs.getBool( XML_preserveFormatting, true );
984 maDefModel.mbUseAutoFormat = rAttribs.getBool( XML_useAutoFormatting, false );
985 maDefModel.mbPageOverThenDown = rAttribs.getBool( XML_pageOverThenDown, false );
986 maDefModel.mbSubtotalHiddenItems = rAttribs.getBool( XML_subtotalHiddenItems, false );
987 maDefModel.mbRowGrandTotals = rAttribs.getBool( XML_rowGrandTotals, true );
988 maDefModel.mbColGrandTotals = rAttribs.getBool( XML_colGrandTotals, true );
989 maDefModel.mbFieldPrintTitles = rAttribs.getBool( XML_fieldPrintTitles, false );
990 maDefModel.mbItemPrintTitles = rAttribs.getBool( XML_itemPrintTitles, false );
991 maDefModel.mbMergeItem = rAttribs.getBool( XML_mergeItem, false );
992 maDefModel.mbShowEmptyRow = rAttribs.getBool( XML_showEmptyRow, false );
993 maDefModel.mbShowEmptyCol = rAttribs.getBool( XML_showEmptyCol, false );
994 maDefModel.mbShowHeaders = rAttribs.getBool( XML_showHeaders, true );
995 maDefModel.mbFieldListSortAsc = rAttribs.getBool( XML_fieldListSortAscending, false );
996 maDefModel.mbCustomListSort = rAttribs.getBool( XML_customListSort, true );
997 maDefModel.mbApplyNumFmt = rAttribs.getBool( XML_applyNumberFormats, false );
998 maDefModel.mbApplyFont = rAttribs.getBool( XML_applyFontFormats, false );
999 maDefModel.mbApplyAlignment = rAttribs.getBool( XML_applyAlignmentFormats, false );
1000 maDefModel.mbApplyBorder = rAttribs.getBool( XML_applyBorderFormats, false );
1001 maDefModel.mbApplyFill = rAttribs.getBool( XML_applyPatternFormats, false );
1002 // OOXML and BIFF12 documentation differ: OOXML mentions width/height, BIFF12 mentions protection
1003 maDefModel.mbApplyProtection = rAttribs.getBool( XML_applyWidthHeightFormats, false );
1006 void PivotTable::importLocation( const AttributeList& rAttribs, sal_Int16 nSheet )
1008 AddressConverter::convertToCellRangeUnchecked( maLocationModel.maRange, rAttribs.getString( XML_ref, OUString() ), nSheet );
1009 maLocationModel.mnFirstHeaderRow = rAttribs.getInteger( XML_firstHeaderRow, 0 );
1010 maLocationModel.mnFirstDataRow = rAttribs.getInteger( XML_firstDataRow, 0 );
1011 maLocationModel.mnFirstDataCol = rAttribs.getInteger( XML_firstDataCol, 0 );
1012 maLocationModel.mnRowPageCount = rAttribs.getInteger( XML_rowPageCount, 0 );
1013 maLocationModel.mnColPageCount = rAttribs.getInteger( XML_colPageCount, 0 );
1016 void PivotTable::importRowField( const AttributeList& rAttribs )
1018 importField( maRowFields, rAttribs );
1021 void PivotTable::importColField( const AttributeList& rAttribs )
1023 importField( maColFields, rAttribs );
1026 void PivotTable::importPageField( const AttributeList& rAttribs )
1028 PTPageFieldModel aModel;
1029 aModel.maName = rAttribs.getXString( XML_name, OUString() );
1030 aModel.mnField = rAttribs.getInteger( XML_fld, -1 );
1031 // specification is wrong, XML_item is not the cache item, but the field item
1032 aModel.mnItem = rAttribs.getInteger( XML_item, BIFF12_PTPAGEFIELD_MULTIITEMS );
1033 maPageFields.push_back( aModel );
1036 void PivotTable::importDataField( const AttributeList& rAttribs )
1038 PTDataFieldModel aModel;
1039 aModel.maName = rAttribs.getXString( XML_name, OUString() );
1040 aModel.mnField = rAttribs.getInteger( XML_fld, -1 );
1041 aModel.mnSubtotal = rAttribs.getToken( XML_subtotal, XML_sum );
1042 aModel.mnShowDataAs = rAttribs.getToken( XML_showDataAs, XML_normal );
1043 aModel.mnBaseField = rAttribs.getInteger( XML_baseField, -1 );
1044 aModel.mnBaseItem = rAttribs.getInteger( XML_baseItem, -1 );
1045 aModel.mnNumFmtId = rAttribs.getInteger( XML_numFmtId, 0 );
1046 maDataFields.push_back( aModel );
1049 void PivotTable::putToInteropGrabBag(const OUString& sName, const AttributeList& rAttribs)
1051 if (auto xFastAttributeList = rAttribs.getFastAttributeList())
1053 // Store both known and unknown attribute sequences to the grab bag as is
1054 css::uno::Sequence<css::xml::FastAttribute> aFast = xFastAttributeList->getFastAttributes();
1055 css::uno::Sequence<css::xml::Attribute> aUnk = xFastAttributeList->getUnknownAttributes();
1056 css::uno::Sequence<css::uno::Any> aVal{ css::uno::Any(aFast), css::uno::Any(aUnk) };
1057 maInteropGrabBag[sName] <<= aVal;
1061 void PivotTable::importPTDefinition( SequenceInputStream& rStrm )
1063 sal_uInt32 nFlags1, nFlags2, nFlags3;
1064 sal_uInt8 nDataAxis;
1065 nFlags1 = rStrm.readuInt32();
1066 nFlags2 = rStrm.readuInt32();
1067 nFlags3 = rStrm.readuInt32();
1068 nDataAxis = rStrm.readuChar();
1069 maDefModel.mnPageWrap = rStrm.readuInt8();
1070 rStrm.skip( 2 ); // refresh versions
1071 maDefModel.mnDataPosition = rStrm.readInt32();
1072 maDefModel.mnAutoFormatId = rStrm.readuInt16();
1073 rStrm.skip( 2 ); // unused
1074 maDefModel.mnChartFormat = rStrm.readInt32();
1075 maDefModel.mnCacheId = rStrm.readInt32();
1076 rStrm >> maDefModel.maName;
1077 if( getFlag( nFlags2, BIFF12_PTDEF_HASDATACAPTION ) )
1078 rStrm >> maDefModel.maDataCaption;
1079 if( getFlag( nFlags2, BIFF12_PTDEF_HASGRANDTOTALCAPTION ) )
1080 rStrm >> maDefModel.maGrandTotalCaption;
1081 if( !getFlag( nFlags3, BIFF12_PTDEF_NOERRORCAPTION ) ) // missing flag indicates existing string
1082 rStrm >> maDefModel.maErrorCaption;
1083 if( !getFlag( nFlags3, BIFF12_PTDEF_NOMISSINGCAPTION ) ) // missing flag indicates existing string
1084 rStrm >> maDefModel.maMissingCaption;
1085 if( getFlag( nFlags2, BIFF12_PTDEF_HASPAGESTYLE ) )
1086 rStrm >> maDefModel.maPageStyle;
1087 if( getFlag( nFlags2, BIFF12_PTDEF_HASPIVOTTABLESTYLE ) )
1088 rStrm >> maDefModel.maPivotTableStyle;
1089 if( getFlag( nFlags2, BIFF12_PTDEF_HASVACATEDSTYLE ) )
1090 rStrm >> maDefModel.maVacatedStyle;
1091 if( getFlag( nFlags2, BIFF12_PTDEF_HASTAG ) )
1092 rStrm >> maDefModel.maTag;
1093 if( getFlag( nFlags3, BIFF12_PTDEF_HASCOLHEADERCAPTION ) ) // TODO: right order (col/row)? spec is unclear
1094 rStrm >> maDefModel.maColHeaderCaption;
1095 if( getFlag( nFlags3, BIFF12_PTDEF_HASROWHEADERCAPTION ) )
1096 rStrm >> maDefModel.maRowHeaderCaption;
1098 SAL_WARN_IF(
1099 (nDataAxis != BIFF12_PTDEF_ROWAXIS) && (nDataAxis != BIFF12_PTDEF_COLAXIS),
1100 "sc.filter",
1101 "PivotTable::importPTDefinition - unexpected axis position for data field");
1103 maDefModel.mnIndent = extractValue< sal_uInt8 >( nFlags1, 24, 7 );
1104 maDefModel.mbDataOnRows = nDataAxis == BIFF12_PTDEF_ROWAXIS;
1105 maDefModel.mbShowError = getFlag( nFlags2, BIFF12_PTDEF_SHOWERROR );
1106 maDefModel.mbShowMissing = getFlag( nFlags2, BIFF12_PTDEF_SHOWMISSING );
1107 maDefModel.mbShowItems = getFlag( nFlags1, BIFF12_PTDEF_SHOWITEMS );
1108 maDefModel.mbDisableFieldList = getFlag( nFlags1, BIFF12_PTDEF_DISABLEFIELDLIST );
1109 maDefModel.mbShowCalcMembers = !getFlag( nFlags1, BIFF12_PTDEF_HIDECALCMEMBERS );
1110 maDefModel.mbVisualTotals = !getFlag( nFlags1, BIFF12_PTDEF_WITHHIDDENTOTALS );
1111 maDefModel.mbShowDrill = !getFlag( nFlags1, BIFF12_PTDEF_HIDEDRILL );
1112 maDefModel.mbPrintDrill = getFlag( nFlags1, BIFF12_PTDEF_PRINTDRILL );
1113 maDefModel.mbEnableDrill = getFlag( nFlags2, BIFF12_PTDEF_ENABLEDRILL );
1114 maDefModel.mbPreserveFormatting = getFlag( nFlags2, BIFF12_PTDEF_PRESERVEFORMATTING );
1115 maDefModel.mbUseAutoFormat = getFlag( nFlags2, BIFF12_PTDEF_USEAUTOFORMAT );
1116 maDefModel.mbPageOverThenDown = getFlag( nFlags2, BIFF12_PTDEF_PAGEOVERTHENDOWN );
1117 maDefModel.mbSubtotalHiddenItems = getFlag( nFlags2, BIFF12_PTDEF_SUBTOTALHIDDENITEMS );
1118 maDefModel.mbRowGrandTotals = getFlag( nFlags2, BIFF12_PTDEF_ROWGRANDTOTALS );
1119 maDefModel.mbColGrandTotals = getFlag( nFlags2, BIFF12_PTDEF_COLGRANDTOTALS );
1120 maDefModel.mbFieldPrintTitles = getFlag( nFlags2, BIFF12_PTDEF_FIELDPRINTTITLES );
1121 maDefModel.mbItemPrintTitles = getFlag( nFlags2, BIFF12_PTDEF_ITEMPRINTTITLES );
1122 maDefModel.mbMergeItem = getFlag( nFlags2, BIFF12_PTDEF_MERGEITEM );
1123 maDefModel.mbApplyNumFmt = getFlag( nFlags2, BIFF12_PTDEF_APPLYNUMFMT );
1124 maDefModel.mbApplyFont = getFlag( nFlags2, BIFF12_PTDEF_APPLYFONT );
1125 maDefModel.mbApplyAlignment = getFlag( nFlags2, BIFF12_PTDEF_APPLYALIGNMENT );
1126 maDefModel.mbApplyBorder = getFlag( nFlags2, BIFF12_PTDEF_APPLYBORDER );
1127 maDefModel.mbApplyFill = getFlag( nFlags2, BIFF12_PTDEF_APPLYFILL );
1128 maDefModel.mbApplyProtection = getFlag( nFlags2, BIFF12_PTDEF_APPLYPROTECTION );
1129 maDefModel.mbShowEmptyRow = getFlag( nFlags2, BIFF12_PTDEF_SHOWEMPTYROW );
1130 maDefModel.mbShowEmptyCol = getFlag( nFlags2, BIFF12_PTDEF_SHOWEMPTYCOL );
1131 maDefModel.mbShowHeaders = !getFlag( nFlags1, BIFF12_PTDEF_HIDEHEADERS );
1132 maDefModel.mbFieldListSortAsc = getFlag( nFlags3, BIFF12_PTDEF_FIELDLISTSORTASC );
1133 maDefModel.mbCustomListSort = !getFlag( nFlags3, BIFF12_PTDEF_NOCUSTOMLISTSORT );
1136 void PivotTable::importPTLocation( SequenceInputStream& rStrm, sal_Int16 nSheet )
1138 BinRange aBinRange;
1139 rStrm >> aBinRange;
1140 maLocationModel.mnFirstHeaderRow = rStrm.readInt32();
1141 maLocationModel.mnFirstDataRow = rStrm.readInt32();
1142 maLocationModel.mnFirstDataCol = rStrm.readInt32();
1143 maLocationModel.mnRowPageCount = rStrm.readInt32();
1144 maLocationModel.mnColPageCount = rStrm.readInt32();
1145 AddressConverter::convertToCellRangeUnchecked( maLocationModel.maRange, aBinRange, nSheet );
1148 void PivotTable::importPTRowFields( SequenceInputStream& rStrm )
1150 importFields( maRowFields, rStrm );
1153 void PivotTable::importPTColFields( SequenceInputStream& rStrm )
1155 importFields( maColFields, rStrm );
1158 void PivotTable::importPTPageField( SequenceInputStream& rStrm )
1160 PTPageFieldModel aModel;
1161 sal_uInt8 nFlags;
1162 aModel.mnField = rStrm.readInt32();
1163 aModel.mnItem = rStrm.readInt32();
1164 rStrm.skip( 4 ); // hierarchy
1165 nFlags = rStrm.readuChar();
1166 if( getFlag( nFlags, BIFF12_PTPAGEFIELD_HASNAME ) )
1167 rStrm >> aModel.maName;
1168 maPageFields.push_back( aModel );
1171 void PivotTable::importPTDataField( SequenceInputStream& rStrm )
1173 PTDataFieldModel aModel;
1174 sal_Int32 nSubtotal, nShowDataAs;
1175 sal_uInt8 nHasName;
1176 aModel.mnField = rStrm.readInt32( );
1177 nSubtotal = rStrm.readInt32();
1178 nShowDataAs = rStrm.readInt32();
1179 aModel.mnBaseField = rStrm.readInt32();
1180 aModel.mnBaseItem = rStrm.readInt32();
1181 aModel.mnNumFmtId = rStrm.readInt32();
1182 nHasName = rStrm.readuChar();
1183 if( nHasName == 1 )
1184 rStrm >> aModel.maName;
1185 aModel.setBiffSubtotal( nSubtotal );
1186 aModel.setBiffShowDataAs( nShowDataAs );
1187 maDataFields.push_back( aModel );
1190 PivotTableField& PivotTable::createTableField()
1192 sal_Int32 nFieldIndex = static_cast< sal_Int32 >( maFields.size() );
1193 PivotTableFieldVector::value_type xTableField = std::make_shared<PivotTableField>( *this, nFieldIndex );
1194 maFields.push_back( xTableField );
1195 return *xTableField;
1198 PivotTableFilter& PivotTable::createTableFilter()
1200 PivotTableFilterVector::value_type xTableFilter = std::make_shared<PivotTableFilter>( *this );
1201 maFilters.push_back( xTableFilter );
1202 return *xTableFilter;
1205 void PivotTable::finalizeImport()
1207 if( !getAddressConverter().validateCellRange( maLocationModel.maRange, true, true ) )
1208 return;
1210 mpPivotCache = getPivotCaches().importPivotCacheFragment( maDefModel.mnCacheId );
1211 if( !mpPivotCache || !mpPivotCache->isValidDataSource() || maDefModel.maName.isEmpty() )
1212 return;
1214 // clear destination area of the original pivot table
1217 Reference< XSheetOperation > xSheetOp( getCellRangeFromDoc( maLocationModel.maRange ), UNO_QUERY_THROW );
1218 using namespace ::com::sun::star::sheet::CellFlags;
1219 xSheetOp->clearContents( VALUE | DATETIME | STRING | FORMULA | HARDATTR | STYLES | EDITATTR | FORMATTED );
1221 catch( Exception& )
1227 // create a new data pilot descriptor based on the source data
1228 Reference< XDataPilotTablesSupplier > xDPTablesSupp( getSheetFromDoc( maLocationModel.maRange.aStart.Tab() ), UNO_QUERY_THROW );
1229 Reference< XDataPilotTables > xDPTables( xDPTablesSupp->getDataPilotTables(), UNO_SET_THROW );
1230 mxDPDescriptor.set( xDPTables->createDataPilotDescriptor(), UNO_SET_THROW );
1231 ScRange aRange = mpPivotCache->getSourceRange();
1232 CellRangeAddress aCellRangeAddress( aRange.aStart.Tab(),
1233 aRange.aStart.Col(), aRange.aStart.Row(),
1234 aRange.aEnd.Col(), aRange.aEnd.Row() );
1235 mxDPDescriptor->setSourceRange( aCellRangeAddress );
1236 mxDPDescriptor->setTag( maDefModel.maTag );
1238 // TODO: This is a hack. Eventually we need to convert the whole thing to the internal API.
1239 auto pImpl = comphelper::getUnoTunnelImplementation<ScDataPilotDescriptorBase>(mxDPDescriptor);
1240 if (!pImpl)
1241 return;
1243 mpDPObject = pImpl->GetDPObject();
1244 if (!mpDPObject)
1245 return;
1247 // global data pilot properties
1248 PropertySet aDescProp( mxDPDescriptor );
1249 aDescProp.setProperty( PROP_ColumnGrand, maDefModel.mbColGrandTotals );
1250 aDescProp.setProperty( PROP_RowGrand, maDefModel.mbRowGrandTotals );
1251 aDescProp.setProperty( PROP_ShowFilterButton, false );
1252 aDescProp.setProperty( PROP_DrillDownOnDoubleClick, maDefModel.mbEnableDrill );
1254 // finalize all fields, this finds field names and creates grouping fields
1255 finalizeFieldsImport();
1257 // all row fields
1258 for( const auto& rRowField : maRowFields )
1259 if( PivotTableField* pField = getTableField( rRowField ) )
1260 pField->convertRowField();
1262 // all column fields
1263 for( const auto& rColField : maColFields )
1264 if( PivotTableField* pField = getTableField( rColField ) )
1265 pField->convertColField();
1267 // all page fields
1268 for( const auto& rPageField : maPageFields )
1269 if( PivotTableField* pField = getTableField( rPageField.mnField ) )
1270 pField->convertPageField( rPageField );
1272 // all hidden fields
1273 ::std::set< sal_Int32 > aVisFields;
1274 aVisFields.insert( maRowFields.begin(), maRowFields.end() );
1275 aVisFields.insert( maColFields.begin(), maColFields.end() );
1276 for( const auto& rPageField : maPageFields )
1277 aVisFields.insert( rPageField.mnField );
1278 sal_Int32 nIndex = 0;
1279 for( auto& rxField : maFields )
1281 if( aVisFields.count( nIndex ) == 0 )
1282 rxField->convertHiddenField();
1283 ++nIndex;
1286 // all data fields
1287 for( auto& rDataField : maDataFields )
1289 if( const PivotCacheField* pCacheField = getCacheField( rDataField.mnField ) )
1291 if ( pCacheField-> getGroupBaseField() != -1 )
1292 rDataField.mnField = pCacheField-> getGroupBaseField();
1294 if( PivotTableField* pField = getTableField( rDataField.mnField ) )
1295 pField->convertDataField( rDataField );
1298 // filters
1299 maFilters.forEachMem( &PivotTableFilter::finalizeImport );
1301 // calculate base position of table
1302 CellAddress aPos( maLocationModel.maRange.aStart.Tab(), maLocationModel.maRange.aStart.Col(), maLocationModel.maRange.aStart.Row() );
1303 /* If page fields exist, include them into the destination
1304 area (they are excluded in Excel). Add an extra blank row. */
1305 if( !maPageFields.empty() )
1306 aPos.Row = ::std::max< sal_Int32 >( static_cast< sal_Int32 >( aPos.Row - maPageFields.size() - 1 ), 0 );
1308 // save interop grab bag
1309 mpDPObject->PutInteropGrabBag(std::move(maInteropGrabBag));
1311 // insert the DataPilot table into the sheet
1312 xDPTables->insertNewByName( maDefModel.maName, aPos, mxDPDescriptor );
1314 catch( Exception& )
1316 OSL_FAIL( "PivotTable::finalizeImport - exception while creating the DataPilot table" );
1320 void PivotTable::finalizeFieldsImport()
1322 if (maFields.empty())
1323 return;
1325 /* Check whether group fields are already imported for another table
1326 sharing the same groups. */
1327 ScDPObject* pDPObj = getDPObject();
1328 const ScDocument& rDoc = getDocImport().getDoc();
1329 if (rDoc.HasPivotTable())
1331 const ScDPCollection* pDPCollection = rDoc.GetDPCollection();
1332 assert(pDPCollection != nullptr);
1333 const ScDPDimensionSaveData* pGroups = nullptr;
1334 bool bRefFound = pDPCollection->GetReferenceGroups(*pDPObj, &pGroups);
1335 // Apply reference groups on this table.
1336 if (bRefFound && pGroups && pGroups->HasGroupDimensions()) {
1337 ScDPSaveData* pSaveData = pDPObj->GetSaveData();
1338 if (pSaveData) {
1339 pSaveData->SetDimensionData(pGroups);
1340 pDPObj->ReloadGroupTableData();
1341 maFields.forEachMem(&PivotTableField::finalizeImportBasedOnCache, ::std::cref(mxDPDescriptor));
1342 return;
1347 maFields.forEachMem(&PivotTableField::finalizeImport, ::std::cref(mxDPDescriptor));
1350 void PivotTable::finalizeDateGroupingImport( const Reference< XDataPilotField >& rxBaseDPField, sal_Int32 nBaseFieldIdx )
1352 // process all fields, there is no chaining information in the cache fields
1353 maFields.forEachMem( &PivotTableField::finalizeDateGroupingImport, ::std::cref(rxBaseDPField), nBaseFieldIdx );
1356 void PivotTable::finalizeParentGroupingImport( const Reference< XDataPilotField >& rxBaseDPField,
1357 const PivotCacheField& rBaseCacheField, PivotCacheGroupItemVector& orItemNames )
1359 // try to create parent group fields that group the items of the passed base field
1360 if( PivotTableField* pParentTableField = maFields.get( rBaseCacheField.getParentGroupField() ).get() )
1361 pParentTableField->finalizeParentGroupingImport( rxBaseDPField, rBaseCacheField, orItemNames );
1364 Reference< XDataPilotField > PivotTable::getDataPilotField( const OUString& rFieldName ) const
1366 Reference< XDataPilotField > xDPField;
1367 if( !rFieldName.isEmpty() && mxDPDescriptor.is() ) try
1369 Reference< XNameAccess > xDPFieldsNA( mxDPDescriptor->getDataPilotFields(), UNO_QUERY_THROW );
1370 xDPField.set( xDPFieldsNA->getByName( rFieldName ), UNO_QUERY );
1372 catch( Exception& )
1375 return xDPField;
1378 Reference< XDataPilotField > PivotTable::getDataPilotField( sal_Int32 nFieldIdx ) const
1380 Reference< XDataPilotField > xDPField;
1381 if( const PivotTableField* pTableField = maFields.get( nFieldIdx ).get() )
1382 xDPField = getDataPilotField( pTableField->getDPFieldName() );
1383 return xDPField;
1386 Reference< XDataPilotField > PivotTable::getDataLayoutField() const
1388 Reference< XDataPilotField > xDPField;
1391 Reference< XDataPilotDataLayoutFieldSupplier > xDPDataFieldSupp( mxDPDescriptor, UNO_QUERY_THROW );
1392 xDPField = xDPDataFieldSupp->getDataLayoutField();
1394 catch( Exception& )
1397 return xDPField;
1400 PivotCacheField* PivotTable::getCacheField( sal_Int32 nFieldIdx )
1402 return mpPivotCache ? mpPivotCache->getCacheField( nFieldIdx ) : nullptr;
1405 const PivotCacheField* PivotTable::getCacheField( sal_Int32 nFieldIdx ) const
1407 return mpPivotCache ? mpPivotCache->getCacheField( nFieldIdx ) : nullptr;
1410 const PivotCacheField* PivotTable::getCacheFieldOfDataField( sal_Int32 nDataItemIdx ) const
1412 const PTDataFieldModel* pDataField = ContainerHelper::getVectorElement( maDataFields, nDataItemIdx );
1413 return pDataField ? getCacheField( pDataField->mnField ) : nullptr;
1416 sal_Int32 PivotTable::getCacheDatabaseIndex( sal_Int32 nFieldIdx ) const
1418 return mpPivotCache ? mpPivotCache->getCacheDatabaseIndex( nFieldIdx ) : -1;
1421 // private --------------------------------------------------------------------
1423 PivotTableField* PivotTable::getTableField( sal_Int32 nFieldIdx )
1425 return (nFieldIdx == OOX_PT_DATALAYOUTFIELD) ? &maDataField : maFields.get( nFieldIdx ).get();
1428 void PivotTable::importField( IndexVector& orFields, const AttributeList& rAttribs )
1430 orFields.push_back( rAttribs.getInteger( XML_x, -1 ) );
1433 void PivotTable::importFields( IndexVector& orFields, SequenceInputStream& rStrm )
1435 OSL_ENSURE( orFields.empty(), "PivotTable::importFields - multiple record instances" );
1436 orFields.clear();
1437 sal_Int32 nCount = rStrm.readInt32();
1438 OSL_ENSURE( 4 * nCount == rStrm.getRemaining(), "PivotTable::importFields - invalid field count" );
1439 nCount = static_cast< sal_Int32 >( rStrm.getRemaining() / 4 );
1440 for( sal_Int32 nIdx = 0; nIdx < nCount; ++nIdx )
1441 orFields.push_back( rStrm.readInt32() );
1444 PivotTableBuffer::PivotTableBuffer( const WorkbookHelper& rHelper ) :
1445 WorkbookHelper( rHelper )
1449 PivotTable& PivotTableBuffer::createPivotTable()
1451 PivotTableVector::value_type xTable = std::make_shared<PivotTable>( *this );
1452 maTables.push_back( xTable );
1453 return *xTable;
1456 void PivotTableBuffer::finalizeImport()
1458 maTables.forEachMem( &PivotTable::finalizeImport );
1461 } // namespace oox
1463 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */