LibreOffice Module sc (master)  1
pivottablebuffer.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include <pivottablebuffer.hxx>
21 
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>
47 #include <oox/token/properties.hxx>
48 #include <oox/token/tokens.hxx>
49 #include <addressconverter.hxx>
50 #include <biffhelper.hxx>
51 
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>
59 
60 namespace oox::xls {
61 
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;
66 
67 namespace {
68 
69 const sal_Int32 OOX_PT_DATALAYOUTFIELD = -2;
70 
71 const sal_Int32 OOX_PT_PREVIOUS_ITEM = 0x001000FC;
72 const sal_Int32 OOX_PT_NEXT_ITEM = 0x001000FD;
73 
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;
87 
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;
98 
99 const sal_uInt16 BIFF12_PTFITEM_HIDDEN = 0x0001;
100 const sal_uInt16 BIFF12_PTFITEM_HIDEDETAILS = 0x0002;
101 
102 const sal_uInt8 BIFF12_PTPAGEFIELD_HASNAME = 0x01;
103 const sal_Int32 BIFF12_PTPAGEFIELD_MULTIITEMS = 0x001000FE;
104 
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;
109 
110 const sal_uInt8 BIFF12_TOP10FILTER_TOP = 0x01;
111 const sal_uInt8 BIFF12_TOP10FILTER_PERCENT = 0x02;
112 
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;
120 
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;
147 
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;
154 
155 const sal_uInt8 BIFF12_PTDEF_ROWAXIS = 1;
156 const sal_uInt8 BIFF12_PTDEF_COLAXIS = 2;
157 
158 } // namespace
159 
161  mnCacheItem( -1 ),
162  mnType( XML_data ),
163  mbShowDetails( true ),
164  mbHidden( false )
165 {
166 }
167 
169 {
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 );
174 }
175 
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 )
205 {
206 }
207 
209 {
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 );
220 }
221 
223  mnField( -1 ),
224  mnItem( BIFF12_PTPAGEFIELD_MULTIITEMS )
225 {
226 }
227 
229  mnField( -1 ),
230  mnSubtotal( XML_sum ),
231  mnShowDataAs( XML_normal ),
232  mnBaseField( -1 ),
233  mnBaseItem( -1 ),
234  mnNumFmtId( 0 )
235 {
236 }
237 
238 void PTDataFieldModel::setBiffSubtotal( sal_Int32 nSubtotal )
239 {
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 );
242 }
243 
244 void PTDataFieldModel::setBiffShowDataAs( sal_Int32 nShowDataAs )
245 {
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 );
248 }
249 
250 PivotTableField::PivotTableField( PivotTable& rPivotTable, sal_Int32 nFieldIndex ) :
251  WorkbookHelper( rPivotTable ),
252  mrPivotTable( rPivotTable ),
253  mnFieldIndex( nFieldIndex )
254 {
255 }
256 
258 {
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 );
290 }
291 
293 {
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 );
301 }
302 
304 {
305  // field index is stored as unsigned integer
306  maModel.mnSortRefField = static_cast< sal_Int32 >( rAttribs.getUnsigned( XML_field, SAL_MAX_UINT32 ) );
307 }
308 
310 {
311  maModel.mnSortRefItem = rAttribs.getInteger( XML_v, -1 );
312 }
313 
315 {
316  sal_uInt32 nFlags1, nFlags2;
317  nFlags1 = rStrm.readuInt32();
318  maModel.mnNumFmtId = rStrm.readInt32();
319  nFlags2 = rStrm.readuInt32();
322 
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 );
337 
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 );
346 
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;
350 }
351 
353 {
354  PTFieldItemModel aModel;
356  sal_uInt16 nFlags;
357  nType = rStrm.readuChar();
358  nFlags = rStrm.readuInt16();
359  aModel.mnCacheItem = rStrm.readInt32();
360 
361  aModel.setBiffType( nType );
362  aModel.mbShowDetails = !getFlag( nFlags, BIFF12_PTFITEM_HIDEDETAILS );
363  aModel.mbHidden = getFlag( nFlags, BIFF12_PTFITEM_HIDDEN );
364 
365  maItems.push_back( aModel );
366 }
367 
369 {
370  maModel.mnSortRefField = rStrm.readInt32();
371 }
372 
374 {
375  maModel.mnSortRefItem = rStrm.readInt32();
376 }
377 
378 void PivotTableField::finalizeImport( const Reference< XDataPilotDescriptor >& rxDPDesc )
379 {
380  /* Process all fields based on source data, other fields (e.g. group
381  fields) are processed from here. PivotCacahe::getDatabaseIndex()
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() ) try
386  {
387  // try to get the source field and its name from passed DataPilot descriptor
388  Reference< XIndexAccess > xDPFieldsIA( rxDPDesc->getDataPilotFields(), UNO_SET_THROW );
389  xDPField.set( xDPFieldsIA->getByIndex( nDatabaseIdx ), UNO_QUERY_THROW );
390  Reference< XNamed > xDPFieldName( xDPField, UNO_QUERY_THROW );
391  maDPFieldName = xDPFieldName->getName();
392  OSL_ENSURE( !maDPFieldName.isEmpty(), "PivotTableField::finalizeImport - no field name in source data found" );
393 
394  // try to convert grouping settings
395  if( const PivotCacheField* pCacheField = mrPivotTable.getCacheField( mnFieldIndex ) )
396  {
397  // numeric grouping is done inplace, no nested group fields will appear
398  if( pCacheField->hasNumericGrouping() )
399  {
400  pCacheField->convertNumericGrouping( xDPField );
401  }
402  else if( pCacheField->hasDateGrouping() )
403  {
404  // first date group settings are inplace
405  pCacheField->createDateGroupField( xDPField );
406  // create all nested group fields (if any)
408  }
409  else if( pCacheField->hasParentGrouping() )
410  {
411 
412  // create a list of all item names, needed to map between original and group items
413  ::std::vector< OUString > aItems;
414  pCacheField->getCacheItemNames( aItems );
415  PivotCacheGroupItemVector aItemNames;
416  for( const auto& rItem : aItems )
417  aItemNames.emplace_back( rItem );
418  // create all nested group fields (if any)
419  mrPivotTable.finalizeParentGroupingImport( xDPField, *pCacheField, aItemNames );
420  }
421  }
422  }
423  catch( Exception& )
424  {
425  }
426 }
427 
428 void PivotTableField::finalizeDateGroupingImport( const Reference< XDataPilotField >& rxBaseDPField, sal_Int32 nBaseFieldIdx )
429 {
430  if( maDPFieldName.isEmpty() ) // prevent endless loops if file format is broken
431  {
433  {
434  if( !pCacheField->isDatabaseField() && pCacheField->hasDateGrouping() && (pCacheField->getGroupBaseField() == nBaseFieldIdx) )
435  {
436  maDPFieldName = pCacheField->createDateGroupField( rxBaseDPField );
437  pCacheField->setFinalGroupName(maDPFieldName);
438  OSL_ENSURE( !maDPFieldName.isEmpty(), "PivotTableField::finalizeDateGroupingImport - cannot create date group field" );
439  }
440  }
441  }
442 }
443 
444 void PivotTableField::finalizeParentGroupingImport( const Reference< XDataPilotField >& rxBaseDPField, const PivotCacheField& rBaseCacheField, PivotCacheGroupItemVector& orItemNames )
445 {
446  if( maDPFieldName.isEmpty() ) // prevent endless loops if file format is broken
447  {
449  {
450  // data field can have user defined groupname captions, apply them
451  // if they do
452  IdCaptionPairList captionList;
453  for( const auto& rItem : maItems )
454  {
455  if ( rItem.mnType == XML_data && rItem.msCaption.getLength() )
456  captionList.emplace_back( rItem.mnCacheItem, rItem.msCaption );
457  }
458  if ( !captionList.empty() )
459  pCacheField->applyItemCaptions( captionList );
460 
461  maDPFieldName = pCacheField->createParentGroupField( rxBaseDPField, rBaseCacheField, orItemNames );
462  pCacheField->setFinalGroupName(maDPFieldName);
463  // on success, try to create nested group fields
464  Reference< XDataPilotField > xDPField = mrPivotTable.getDataPilotField( maDPFieldName );
465  if( xDPField.is() )
466  mrPivotTable.finalizeParentGroupingImport( xDPField, *pCacheField, orItemNames );
467  }
468  }
469 }
470 
471 void PivotTableField::finalizeImportBasedOnCache( const Reference< XDataPilotDescriptor >& rxDPDesc)
472 {
473  /* Process all fields based on source data, other fields (e.g. group
474  fields) are processed based on cache fields.*/
475  Reference< XDataPilotField > xDPField;
476  sal_Int32 nDatabaseIdx = mrPivotTable.getCacheDatabaseIndex( mnFieldIndex );
477  if( (nDatabaseIdx >= 0) && rxDPDesc.is() ) try
478  {
479  // Try to get the source field and its name from passed DataPilot descriptor
480  Reference< XIndexAccess > xDPFieldsIA( rxDPDesc->getDataPilotFields(), UNO_SET_THROW );
481  xDPField.set( xDPFieldsIA->getByIndex( nDatabaseIdx ), UNO_QUERY_THROW );
482  Reference< XNamed > xDPFieldName( xDPField, UNO_QUERY_THROW );
483  maDPFieldName = xDPFieldName->getName();
484  SAL_WARN_IF( maDPFieldName.isEmpty(), "sc.filter", "PivotTableField::finalizeImportBasedOnCache - no field name in source data found" );
485  }
486  catch( Exception& )
487  {
488  }
489 
490  // Use group names already generated for another table using the same group field.
491  if( const PivotCacheField* pCacheField = mrPivotTable.getCacheField( mnFieldIndex ) )
492  {
493  if(!pCacheField->getFinalGroupName().isEmpty())
494  maDPFieldName = pCacheField->getFinalGroupName();
495  }
496 }
497 
499 {
500  convertRowColPageField( XML_axisRow );
501 }
502 
504 {
505  convertRowColPageField( XML_axisCol );
506 }
507 
509 {
511 }
512 
514 {
515  OSL_ENSURE( rPageField.mnField == mnFieldIndex, "PivotTableField::convertPageField - wrong field index" );
516  // convert all settings common for row/column/page fields
517  Reference< XDataPilotField > xDPField = convertRowColPageField( XML_axisPage );
518 
519  if( xDPField.is() )
520  {
521  PropertySet aPropSet( xDPField );
522 
523  // find cache item used as 'selected page'
524  sal_Int32 nCacheItem = -1;
526  {
527  // multiple items may be selected
528  OSL_ENSURE( rPageField.mnItem == BIFF12_PTPAGEFIELD_MULTIITEMS, "PivotTableField::convertPageField - unexpected cache item index" );
529  // try to find a single visible item
530  bool bHasMultiItems = false;
531  for( const auto& rItem : maItems )
532  {
533  if( (rItem.mnType == XML_data) && !rItem.mbHidden )
534  {
535  bHasMultiItems = nCacheItem >= 0;
536  nCacheItem = bHasMultiItems ? -1 : rItem.mnCacheItem;
537  }
538 
539  if( bHasMultiItems )
540  break;
541  }
542  }
543  else
544  {
545  // single item may be selected
546  if( (0 <= rPageField.mnItem) && (rPageField.mnItem < static_cast< sal_Int32 >( maItems.size() )) )
547  nCacheItem = maItems[ rPageField.mnItem ].mnCacheItem;
548  }
549 
550  if( nCacheItem >= 0 )
551  {
552  if( const PivotCacheField* pCacheField = mrPivotTable.getCacheField( mnFieldIndex ) )
553  {
554  if( const PivotCacheItem* pSharedItem = pCacheField->getCacheItem( nCacheItem ) )
555  {
556  ScDPObject* pDPObj = mrPivotTable.getDPObject();
557  ScDPSaveData* pSaveData = pDPObj->GetSaveData();
558  ScDPSaveDimension* pDim = pSaveData->GetDimensionByName(pCacheField->getName());
559  OUString aSelectedPage = pSharedItem->getFormattedName(*pDim, pDPObj, DateTime(getWorkbookSettings().getNullDate()));
560  aPropSet.setProperty( PROP_SelectedPage, aSelectedPage );
561  }
562  }
563  }
564  }
565 }
566 
568 {
569  OSL_ENSURE( rDataField.mnField == mnFieldIndex, "PivotTableField::convertDataField - wrong field index" );
570  OSL_ENSURE( maModel.mbDataField, "PivotTableField::convertDataField - not a data field" );
571  Reference< XDataPilotField > xDPField = mrPivotTable.getDataPilotField( maDPFieldName );
572  if( xDPField.is() )
573  {
574  PropertySet aPropSet( xDPField );
575 
576  // field orientation
577  aPropSet.setProperty( PROP_Orientation, DataPilotFieldOrientation_DATA );
578 
579  if (!rDataField.maName.isEmpty())
580  aPropSet.setProperty(PROP_Name, rDataField.maName);
581 
582  /* Field aggregation function. Documentation is a little bit confused
583  about which names to use for the count functions. The name 'count'
584  means 'count all', and 'countNum' means 'count numbers'. On the
585  other hand, for subtotals, 'countA' means 'count all', and 'count'
586  means 'count numbers' (see above). */
587  GeneralFunction eAggFunc = GeneralFunction_SUM;
588  switch( rDataField.mnSubtotal )
589  {
590  case XML_sum: eAggFunc = GeneralFunction_SUM; break;
591  case XML_count: eAggFunc = GeneralFunction_COUNT; break;
592  case XML_average: eAggFunc = GeneralFunction_AVERAGE; break;
593  case XML_max: eAggFunc = GeneralFunction_MAX; break;
594  case XML_min: eAggFunc = GeneralFunction_MIN; break;
595  case XML_product: eAggFunc = GeneralFunction_PRODUCT; break;
596  case XML_countNums: eAggFunc = GeneralFunction_COUNTNUMS; break;
597  case XML_stdDev: eAggFunc = GeneralFunction_STDEV; break;
598  case XML_stdDevp: eAggFunc = GeneralFunction_STDEVP; break;
599  case XML_var: eAggFunc = GeneralFunction_VAR; break;
600  case XML_varp: eAggFunc = GeneralFunction_VARP; break;
601  default: OSL_FAIL( "PivotTableField::convertDataField - unknown aggregation function" );
602  }
603  aPropSet.setProperty( PROP_Function, eAggFunc );
604 
605  // field reference ('show data as')
606  DataPilotFieldReference aReference;
607  aReference.ReferenceType = DataPilotFieldReferenceType::NONE;
608  switch( rDataField.mnShowDataAs )
609  {
610  case XML_difference: aReference.ReferenceType = DataPilotFieldReferenceType::ITEM_DIFFERENCE; break;
611  case XML_percent: aReference.ReferenceType = DataPilotFieldReferenceType::ITEM_PERCENTAGE; break;
612  case XML_percentDiff: aReference.ReferenceType = DataPilotFieldReferenceType::ITEM_PERCENTAGE_DIFFERENCE; break;
613  case XML_runTotal: aReference.ReferenceType = DataPilotFieldReferenceType::RUNNING_TOTAL; break;
614  case XML_percentOfRow: aReference.ReferenceType = DataPilotFieldReferenceType::ROW_PERCENTAGE; break;
615  case XML_percentOfCol: aReference.ReferenceType = DataPilotFieldReferenceType::COLUMN_PERCENTAGE; break;
616  case XML_percentOfTotal: aReference.ReferenceType = DataPilotFieldReferenceType::TOTAL_PERCENTAGE; break;
617  case XML_index: aReference.ReferenceType = DataPilotFieldReferenceType::INDEX; break;
618  }
619  if( aReference.ReferenceType != DataPilotFieldReferenceType::NONE )
620  {
621  if( const PivotCacheField* pCacheField = mrPivotTable.getCacheField( rDataField.mnBaseField ) )
622  {
623  aReference.ReferenceField = pCacheField->getName();
624  switch( rDataField.mnBaseItem )
625  {
626  case OOX_PT_PREVIOUS_ITEM:
627  aReference.ReferenceItemType = DataPilotFieldReferenceItemType::PREVIOUS;
628  break;
629  case OOX_PT_NEXT_ITEM:
630  aReference.ReferenceItemType = DataPilotFieldReferenceItemType::NEXT;
631  break;
632  default:
633  aReference.ReferenceItemType = DataPilotFieldReferenceItemType::NAMED;
634  if( const PivotCacheItem* pCacheItem = pCacheField->getCacheItem( rDataField.mnBaseItem ) )
635  aReference.ReferenceItemName = pCacheItem->getName();
636  }
637  aPropSet.setProperty( PROP_Reference, aReference );
638  }
639  }
640  }
641 }
642 
643 // private --------------------------------------------------------------------
644 
645 Reference< XDataPilotField > PivotTableField::convertRowColPageField( sal_Int32 nAxis )
646 {
647  bool bDataLayout = mnFieldIndex == OOX_PT_DATALAYOUTFIELD;
648  Reference< XDataPilotField > xDPField = bDataLayout ? mrPivotTable.getDataLayoutField() : mrPivotTable.getDataPilotField( maDPFieldName );
649  OSL_ENSURE( bDataLayout || (nAxis == maModel.mnAxis), "PivotTableField::convertRowColPageField - field axis mismatch" );
650 
651  if( xDPField.is() )
652  {
653  // TODO: Use this to set properties directly, bypassing the slow uno layer.
654  ScDPObject* pDPObj = mrPivotTable.getDPObject();
655 
656  PropertySet aPropSet( xDPField );
657 
658  // field orientation
659  DataPilotFieldOrientation eFieldOrient = DataPilotFieldOrientation_HIDDEN;
660  switch( nAxis )
661  {
662  case XML_axisRow: eFieldOrient = DataPilotFieldOrientation_ROW; break;
663  case XML_axisCol: eFieldOrient = DataPilotFieldOrientation_COLUMN; break;
664  case XML_axisPage: eFieldOrient = DataPilotFieldOrientation_PAGE; break;
665  }
666  if( eFieldOrient != DataPilotFieldOrientation_HIDDEN )
667  aPropSet.setProperty( PROP_Orientation, eFieldOrient );
668 
669  // all other settings not for the data layout field
670  if( !bDataLayout )
671  {
672  /* Field subtotal functions. Ignore the 'defaultSubtotal' flag, if
673  explicit functions are set. This is different behaviour between
674  XML (where 'defaultSubtotal' is set regardless of other
675  functions) and binary formats (where 'defaultSubtotal' is not
676  set if other functions are set). */
677  ::std::vector< GeneralFunction > aSubtotals;
678  /* Order of subtotals is fixed in Excel. Documentation is a little
679  bit confused about which names to use for the count functions.
680  For subtotals, 'countA' means 'count all', and 'count' means
681  'count numbers'. On the other hand, for the data field
682  aggregation function, 'count' means 'count all', and 'countNum'
683  means 'count numbers' (see below). */
684  if( maModel.mbSumSubtotal ) aSubtotals.push_back( GeneralFunction_SUM );
685  if( maModel.mbCountASubtotal ) aSubtotals.push_back( GeneralFunction_COUNT );
686  if( maModel.mbAverageSubtotal ) aSubtotals.push_back( GeneralFunction_AVERAGE );
687  if( maModel.mbMaxSubtotal ) aSubtotals.push_back( GeneralFunction_MAX );
688  if( maModel.mbMinSubtotal ) aSubtotals.push_back( GeneralFunction_MIN );
689  if( maModel.mbProductSubtotal ) aSubtotals.push_back( GeneralFunction_PRODUCT );
690  if( maModel.mbCountSubtotal ) aSubtotals.push_back( GeneralFunction_COUNTNUMS );
691  if( maModel.mbStdDevSubtotal ) aSubtotals.push_back( GeneralFunction_STDEV );
692  if( maModel.mbStdDevPSubtotal ) aSubtotals.push_back( GeneralFunction_STDEVP );
693  if( maModel.mbVarSubtotal ) aSubtotals.push_back( GeneralFunction_VAR );
694  if( maModel.mbVarPSubtotal ) aSubtotals.push_back( GeneralFunction_VARP );
695  // if no function is set manually, check the 'defaultSubtotal' flag
696  if( aSubtotals.empty() && maModel.mbDefaultSubtotal )
697  aSubtotals.push_back( GeneralFunction_AUTO );
698  aPropSet.setProperty( PROP_Subtotals, ContainerHelper::vectorToSequence( aSubtotals ) );
699 
700  // layout settings
701  DataPilotFieldLayoutInfo aLayoutInfo;
702  aLayoutInfo.LayoutMode = maModel.mbOutline ?
703  (maModel.mbSubtotalTop ? DataPilotFieldLayoutMode::OUTLINE_SUBTOTALS_TOP : DataPilotFieldLayoutMode::OUTLINE_SUBTOTALS_BOTTOM) :
704  DataPilotFieldLayoutMode::TABULAR_LAYOUT;
705  aLayoutInfo.AddEmptyLines = maModel.mbInsertBlankRow;
706  aPropSet.setProperty( PROP_LayoutInfo, aLayoutInfo );
707  aPropSet.setProperty( PROP_ShowEmpty, maModel.mbShowAll );
708 
709  // auto show (OOXML/BIFF12 only)
710  if( maModel.mbAutoShow )
711  {
712  DataPilotFieldAutoShowInfo aAutoShowInfo;
713  aAutoShowInfo.IsEnabled = true;
714  aAutoShowInfo.ShowItemsMode = maModel.mbTopAutoShow ? DataPilotFieldShowItemsMode::FROM_TOP : DataPilotFieldShowItemsMode::FROM_BOTTOM;
715  aAutoShowInfo.ItemCount = maModel.mnAutoShowItems;
717  aAutoShowInfo.DataField = pCacheField->getName();
718  aPropSet.setProperty( PROP_AutoShowInfo, aAutoShowInfo );
719  }
720 
721  // auto sort
722  DataPilotFieldSortInfo aSortInfo;
723  aSortInfo.IsAscending = maModel.mnSortType == XML_ascending;
724  if( (maModel.mnSortType != XML_ascending) && (maModel.mnSortType != XML_descending) )
725  {
726  aSortInfo.Mode = DataPilotFieldSortMode::MANUAL;
727  }
728  else
729  {
730  const PivotCacheField* pCacheField = (maModel.mnSortRefField == OOX_PT_DATALAYOUTFIELD) ?
732  if( pCacheField )
733  {
734  aSortInfo.Mode = DataPilotFieldSortMode::DATA;
735  aSortInfo.Field = pCacheField->getName();
736  }
737  else
738  {
739  aSortInfo.Mode = DataPilotFieldSortMode::NAME;
740  }
741  }
742  aPropSet.setProperty( PROP_SortInfo, aSortInfo );
743 
744  // item settings
745  if (const PivotCacheField* pCacheField = mrPivotTable.getCacheField(mnFieldIndex))
746  {
747  ScDPSaveData* pSaveData = pDPObj->GetSaveData();
748  ScDPSaveDimension* pDim = pSaveData->GetDimensionByName(pCacheField->getName());
749 
750  try
751  {
752  for( const auto& rItem : maItems )
753  {
754  if (rItem.mnType != XML_data)
755  continue;
756 
757  const PivotCacheItem* pSharedItem = pCacheField->getCacheItem(rItem.mnCacheItem);
758  if (!pSharedItem)
759  continue;
760 
761  try
762  {
763  ScDPSaveMember* pMem = pDim->GetMemberByName(pSharedItem->getFormattedName(*pDim, pDPObj, DateTime(getWorkbookSettings().getNullDate())));
764  pMem->SetShowDetails(rItem.mbShowDetails);
765  pMem->SetIsVisible(!rItem.mbHidden);
766  }
767  catch( Exception& )
768  {
769  // catch every failed container access to be able to process following items
770  }
771  }
772  }
773  catch (const Exception&) {}
774  }
775  }
776  }
777  return xDPField;
778 }
779 
781  mfValue( 0.0 ),
782  mnField( -1 ),
783  mnMemPropField( -1 ),
785  mnEvalOrder( 0 ),
786  mnId( -1 ),
787  mnMeasureField( -1 ),
788  mnMeasureHier( -1 ),
789  mbTopFilter( true )
790 {
791 }
792 
794  WorkbookHelper( rPivotTable ),
795  mrPivotTable( rPivotTable )
796 {
797 }
798 
800 {
801  maModel.maName = rAttribs.getXString( XML_name, OUString() );
802  maModel.maDescription = rAttribs.getXString( XML_description, OUString() );
803  maModel.maStrValue1 = rAttribs.getXString( XML_stringValue1, OUString() );
804  maModel.maStrValue2 = rAttribs.getXString( XML_stringValue2, OUString() );
805  maModel.mnField = rAttribs.getInteger( XML_fld, -1 );
806  maModel.mnMemPropField = rAttribs.getInteger( XML_mpFld, -1 );
807  maModel.mnType = rAttribs.getToken( XML_type, XML_TOKEN_INVALID );
808  maModel.mnEvalOrder = rAttribs.getInteger( XML_evalOrder, 0 );
809  maModel.mnId = rAttribs.getInteger( XML_id, -1 );
810  maModel.mnMeasureField = rAttribs.getInteger( XML_iMeasureFld, -1 );
811  maModel.mnMeasureHier = rAttribs.getInteger( XML_iMeasureHier, -1 );
812 }
813 
815 {
816  OSL_ENSURE( rAttribs.getBool( XML_percent, false ) == (maModel.mnType == XML_percent),
817  "PivotTableFilter::importTop10 - unexpected value of percent attribute" );
818  maModel.mfValue = rAttribs.getDouble( XML_val, 0.0 );
819  maModel.mbTopFilter = rAttribs.getBool( XML_top, true );
820 }
821 
823 {
824  sal_Int32 nType;
825  sal_uInt16 nFlags;
826  maModel.mnField = rStrm.readInt32();
827  maModel.mnMemPropField = rStrm.readInt32();
828  nType = rStrm.readInt32();
829  rStrm.skip( 4 ); // unused
830  maModel.mnId = rStrm.readInt32();
831  maModel.mnMeasureField = rStrm.readInt32();
832  maModel.mnMeasureHier = rStrm.readInt32();
833  nFlags = rStrm.readuInt16();
834  if( getFlag( nFlags, BIFF12_PTFILTER_HASNAME ) )
835  rStrm >> maModel.maName;
836  if( getFlag( nFlags, BIFF12_PTFILTER_HASDESCRIPTION ) )
837  rStrm >> maModel.maDescription;
838  if( getFlag( nFlags, BIFF12_PTFILTER_HASSTRVALUE1 ) )
839  rStrm >> maModel.maStrValue1;
840  if( getFlag( nFlags, BIFF12_PTFILTER_HASSTRVALUE2 ) )
841  rStrm >> maModel.maStrValue2;
842 
843  static const sal_Int32 spnTypes[] =
844  {
845  XML_unknown,
846  // data field top10 filter (1-3)
847  XML_count, XML_percent, XML_sum,
848  // caption filter (4-17)
849  XML_captionEqual, XML_captionNotEqual,
850  XML_captionBeginsWith, XML_captionNotBeginsWith, XML_captionEndsWith, XML_captionNotEndsWith,
851  XML_captionContains, XML_captionNotContains, XML_captionGreaterThan, XML_captionGreaterThanOrEqual,
852  XML_captionLessThan, XML_captionLessThanOrEqual, XML_captionBetween, XML_captionNotBetween,
853  // value filter (18-25)
854  XML_valueEqual, XML_valueNotEqual, XML_valueGreaterThan, XML_valueGreaterThanOrEqual,
855  XML_valueLessThan, XML_valueLessThanOrEqual, XML_valueBetween, XML_valueNotBetween,
856  // date filter (26-65)
857  XML_dateEqual, XML_dateOlderThan, XML_dateNewerThan, XML_dateBetween,
858  XML_tomorrow, XML_today, XML_yesterday, XML_nextWeek, XML_thisWeek, XML_lastWeek,
859  XML_nextMonth, XML_thisMonth, XML_lastMonth, XML_nextQuarter, XML_thisQuarter, XML_lastQuarter,
860  XML_nextYear, XML_thisYear, XML_lastYear, XML_yearToDate, XML_Q1, XML_Q2, XML_Q3, XML_Q4,
861  XML_M1, XML_M2, XML_M3, XML_M4, XML_M5, XML_M6, XML_M7, XML_M8, XML_M9, XML_M10, XML_M11, XML_M12,
862  XML_dateNotEqual, XML_dateOlderThanOrEqual, XML_dateNewerThanOrEqual, XML_dateNotBetween
863  };
864  maModel.mnType = STATIC_ARRAY_SELECT( spnTypes, nType, XML_TOKEN_INVALID );
865 }
866 
868 {
869  sal_uInt8 nFlags;
870  nFlags = rStrm.readuChar();
871  maModel.mfValue = rStrm.readDouble();
872 
873  SAL_WARN_IF(
874  getFlag(nFlags, BIFF12_TOP10FILTER_PERCENT) != (maModel.mnType == XML_percent),
875  "sc.filter",
876  "PivotTableFilter::importTop10 - unexpected value of percent attribute");
877  maModel.mbTopFilter = getFlag( nFlags, BIFF12_TOP10FILTER_TOP );
878 }
879 
881 {
882  // only simple top10 filter supported
883  if( maModel.mnType == XML_count )
884  {
886  if( aPropSet.is() )
887  {
888  DataPilotFieldAutoShowInfo aAutoShowInfo;
889  aAutoShowInfo.IsEnabled = true;
890  aAutoShowInfo.ShowItemsMode = maModel.mbTopFilter ? DataPilotFieldShowItemsMode::FROM_TOP : DataPilotFieldShowItemsMode::FROM_BOTTOM;
891  aAutoShowInfo.ItemCount = getLimitedValue< sal_Int32, double >( maModel.mfValue, 0, SAL_MAX_INT32 );
893  aAutoShowInfo.DataField = pCacheField->getName();
894  aPropSet.setProperty( PROP_AutoShowInfo, aAutoShowInfo );
895  }
896  }
897 }
898 
900  mnCacheId( -1 ),
901  mnDataPosition( 0 ),
902  mnPageWrap( 0 ),
903  mnIndent( 1 ),
904  mnChartFormat( 0 ),
905  mbDataOnRows( false ),
906  mbShowError( false ),
907  mbShowMissing( true ),
908  mbShowItems( true ),
909  mbDisableFieldList( false ),
910  mbShowCalcMembers( true ),
911  mbVisualTotals( true ),
912  mbShowDrill( true ),
913  mbPrintDrill( false ),
914  mbEnableDrill( true ),
915  mbPreserveFormatting( true ),
916  mbUseAutoFormat( false ),
917  mbPageOverThenDown( false ),
918  mbSubtotalHiddenItems( false ),
919  mbRowGrandTotals( true ),
920  mbColGrandTotals( true ),
921  mbFieldPrintTitles( false ),
922  mbItemPrintTitles( false ),
923  mbMergeItem( false ),
924  mbShowEmptyRow( false ),
925  mbShowEmptyCol( false ),
926  mbShowHeaders( true ),
927  mbFieldListSortAsc( false ),
928  mbCustomListSort( true )
929 {
930 }
931 
933  mnFirstHeaderRow( 0 ),
934  mnFirstDataRow( 0 ),
935  mnFirstDataCol( 0 ),
936  mnRowPageCount( 0 ),
937  mnColPageCount( 0 )
938 {
939 }
940 
942  WorkbookHelper( rHelper ),
943  mpDPObject(nullptr),
944  maDataField( *this, OOX_PT_DATALAYOUTFIELD ),
945  mpPivotCache( nullptr )
946 {
947 }
948 
950 {
951  maDefModel.maName = rAttribs.getXString( XML_name, OUString() );
952  maDefModel.maDataCaption = rAttribs.getXString( XML_dataCaption , OUString() );
953  maDefModel.maGrandTotalCaption = rAttribs.getXString( XML_grandTotalCaption, OUString() );
954  maDefModel.maRowHeaderCaption = rAttribs.getXString( XML_rowHeaderCaption, OUString() );
955  maDefModel.maColHeaderCaption = rAttribs.getXString( XML_colHeaderCaption, OUString() );
956  maDefModel.maErrorCaption = rAttribs.getXString( XML_errorCaption, OUString() );
957  maDefModel.maMissingCaption = rAttribs.getXString( XML_missingCaption, OUString() );
958  maDefModel.maPageStyle = rAttribs.getXString( XML_pageStyle, OUString() );
959  maDefModel.maPivotTableStyle = rAttribs.getXString( XML_pivotTableStyle, OUString() );
960  maDefModel.maVacatedStyle = rAttribs.getXString( XML_vacatedStyle, OUString() );
961  maDefModel.maTag = rAttribs.getXString( XML_tag, OUString() );
962  maDefModel.mnCacheId = rAttribs.getInteger( XML_cacheId, -1 );
963  maDefModel.mnDataPosition = rAttribs.getInteger( XML_dataPosition, 0 );
964  maDefModel.mnPageWrap = rAttribs.getInteger( XML_pageWrap, 0 );
965  maDefModel.mnIndent = rAttribs.getInteger( XML_indent, 1 );
966  maDefModel.mnChartFormat = rAttribs.getInteger( XML_chartFormat, 0 );
967  maDefModel.mnAutoFormatId = rAttribs.getInteger( XML_autoFormatId, 0 );
968  maDefModel.mbDataOnRows = rAttribs.getBool( XML_dataOnRows, false );
969  maDefModel.mbShowError = rAttribs.getBool( XML_showError, false );
970  maDefModel.mbShowMissing = rAttribs.getBool( XML_showMissing, true );
971  maDefModel.mbShowItems = rAttribs.getBool( XML_showItems, true );
972  maDefModel.mbDisableFieldList = rAttribs.getBool( XML_disableFieldList, false );
973  maDefModel.mbShowCalcMembers = rAttribs.getBool( XML_showCalcMbrs, true );
974  maDefModel.mbVisualTotals = rAttribs.getBool( XML_visualTotals, true );
975  maDefModel.mbShowDrill = rAttribs.getBool( XML_showDrill, true );
976  maDefModel.mbPrintDrill = rAttribs.getBool( XML_printDrill, false );
977  maDefModel.mbEnableDrill = rAttribs.getBool( XML_enableDrill, true );
978  maDefModel.mbPreserveFormatting = rAttribs.getBool( XML_preserveFormatting, true );
979  maDefModel.mbUseAutoFormat = rAttribs.getBool( XML_useAutoFormatting, false );
980  maDefModel.mbPageOverThenDown = rAttribs.getBool( XML_pageOverThenDown, false );
981  maDefModel.mbSubtotalHiddenItems = rAttribs.getBool( XML_subtotalHiddenItems, false );
982  maDefModel.mbRowGrandTotals = rAttribs.getBool( XML_rowGrandTotals, true );
983  maDefModel.mbColGrandTotals = rAttribs.getBool( XML_colGrandTotals, true );
984  maDefModel.mbFieldPrintTitles = rAttribs.getBool( XML_fieldPrintTitles, false );
985  maDefModel.mbItemPrintTitles = rAttribs.getBool( XML_itemPrintTitles, false );
986  maDefModel.mbMergeItem = rAttribs.getBool( XML_mergeItem, false );
987  maDefModel.mbShowEmptyRow = rAttribs.getBool( XML_showEmptyRow, false );
988  maDefModel.mbShowEmptyCol = rAttribs.getBool( XML_showEmptyCol, false );
989  maDefModel.mbShowHeaders = rAttribs.getBool( XML_showHeaders, true );
990  maDefModel.mbFieldListSortAsc = rAttribs.getBool( XML_fieldListSortAscending, false );
991  maDefModel.mbCustomListSort = rAttribs.getBool( XML_customListSort, true );
992  maDefModel.mbApplyNumFmt = rAttribs.getBool( XML_applyNumberFormats, false );
993  maDefModel.mbApplyFont = rAttribs.getBool( XML_applyFontFormats, false );
994  maDefModel.mbApplyAlignment = rAttribs.getBool( XML_applyAlignmentFormats, false );
995  maDefModel.mbApplyBorder = rAttribs.getBool( XML_applyBorderFormats, false );
996  maDefModel.mbApplyFill = rAttribs.getBool( XML_applyPatternFormats, false );
997  // OOXML and BIFF12 documentation differ: OOXML mentions width/height, BIFF12 mentions protection
998  maDefModel.mbApplyProtection = rAttribs.getBool( XML_applyWidthHeightFormats, false );
999 }
1000 
1001 void PivotTable::importLocation( const AttributeList& rAttribs, sal_Int16 nSheet )
1002 {
1003  AddressConverter::convertToCellRangeUnchecked( maLocationModel.maRange, rAttribs.getString( XML_ref, OUString() ), nSheet );
1004  maLocationModel.mnFirstHeaderRow = rAttribs.getInteger( XML_firstHeaderRow, 0 );
1005  maLocationModel.mnFirstDataRow = rAttribs.getInteger( XML_firstDataRow, 0 );
1006  maLocationModel.mnFirstDataCol = rAttribs.getInteger( XML_firstDataCol, 0 );
1007  maLocationModel.mnRowPageCount = rAttribs.getInteger( XML_rowPageCount, 0 );
1008  maLocationModel.mnColPageCount = rAttribs.getInteger( XML_colPageCount, 0 );
1009 }
1010 
1012 {
1013  importField( maRowFields, rAttribs );
1014 }
1015 
1017 {
1018  importField( maColFields, rAttribs );
1019 }
1020 
1022 {
1023  PTPageFieldModel aModel;
1024  aModel.maName = rAttribs.getXString( XML_name, OUString() );
1025  aModel.mnField = rAttribs.getInteger( XML_fld, -1 );
1026  // specification is wrong, XML_item is not the cache item, but the field item
1027  aModel.mnItem = rAttribs.getInteger( XML_item, BIFF12_PTPAGEFIELD_MULTIITEMS );
1028  maPageFields.push_back( aModel );
1029 }
1030 
1032 {
1033  PTDataFieldModel aModel;
1034  aModel.maName = rAttribs.getXString( XML_name, OUString() );
1035  aModel.mnField = rAttribs.getInteger( XML_fld, -1 );
1036  aModel.mnSubtotal = rAttribs.getToken( XML_subtotal, XML_sum );
1037  aModel.mnShowDataAs = rAttribs.getToken( XML_showDataAs, XML_normal );
1038  aModel.mnBaseField = rAttribs.getInteger( XML_baseField, -1 );
1039  aModel.mnBaseItem = rAttribs.getInteger( XML_baseItem, -1 );
1040  aModel.mnNumFmtId = rAttribs.getInteger( XML_numFmtId, 0 );
1041  maDataFields.push_back( aModel );
1042 }
1043 
1044 void PivotTable::putToInteropGrabBag(const OUString& sName, const AttributeList& rAttribs)
1045 {
1046  if (auto xFastAttributeList = rAttribs.getFastAttributeList())
1047  {
1048  // Store both known and unknown attribute sequences to the grab bag as is
1049  css::uno::Sequence<css::xml::FastAttribute> aFast = xFastAttributeList->getFastAttributes();
1050  css::uno::Sequence<css::xml::Attribute> aUnk = xFastAttributeList->getUnknownAttributes();
1051  css::uno::Sequence<css::uno::Any> aVal{ css::uno::Any(aFast), css::uno::Any(aUnk) };
1052  maInteropGrabBag[sName] <<= aVal;
1053  }
1054 }
1055 
1057 {
1058  sal_uInt32 nFlags1, nFlags2, nFlags3;
1059  sal_uInt8 nDataAxis;
1060  nFlags1 = rStrm.readuInt32();
1061  nFlags2 = rStrm.readuInt32();
1062  nFlags3 = rStrm.readuInt32();
1063  nDataAxis = rStrm.readuChar();
1064  maDefModel.mnPageWrap = rStrm.readuInt8();
1065  rStrm.skip( 2 ); // refresh versions
1068  rStrm.skip( 2 ); // unused
1070  maDefModel.mnCacheId = rStrm.readInt32();
1071  rStrm >> maDefModel.maName;
1072  if( getFlag( nFlags2, BIFF12_PTDEF_HASDATACAPTION ) )
1073  rStrm >> maDefModel.maDataCaption;
1074  if( getFlag( nFlags2, BIFF12_PTDEF_HASGRANDTOTALCAPTION ) )
1076  if( !getFlag( nFlags3, BIFF12_PTDEF_NOERRORCAPTION ) ) // missing flag indicates existing string
1077  rStrm >> maDefModel.maErrorCaption;
1078  if( !getFlag( nFlags3, BIFF12_PTDEF_NOMISSINGCAPTION ) ) // missing flag indicates existing string
1079  rStrm >> maDefModel.maMissingCaption;
1080  if( getFlag( nFlags2, BIFF12_PTDEF_HASPAGESTYLE ) )
1081  rStrm >> maDefModel.maPageStyle;
1082  if( getFlag( nFlags2, BIFF12_PTDEF_HASPIVOTTABLESTYLE ) )
1083  rStrm >> maDefModel.maPivotTableStyle;
1084  if( getFlag( nFlags2, BIFF12_PTDEF_HASVACATEDSTYLE ) )
1085  rStrm >> maDefModel.maVacatedStyle;
1086  if( getFlag( nFlags2, BIFF12_PTDEF_HASTAG ) )
1087  rStrm >> maDefModel.maTag;
1088  if( getFlag( nFlags3, BIFF12_PTDEF_HASCOLHEADERCAPTION ) ) // TODO: right order (col/row)? spec is unclear
1089  rStrm >> maDefModel.maColHeaderCaption;
1090  if( getFlag( nFlags3, BIFF12_PTDEF_HASROWHEADERCAPTION ) )
1091  rStrm >> maDefModel.maRowHeaderCaption;
1092 
1093  SAL_WARN_IF(
1094  (nDataAxis != BIFF12_PTDEF_ROWAXIS) && (nDataAxis != BIFF12_PTDEF_COLAXIS),
1095  "sc.filter",
1096  "PivotTable::importPTDefinition - unexpected axis position for data field");
1097 
1098  maDefModel.mnIndent = extractValue< sal_uInt8 >( nFlags1, 24, 7 );
1099  maDefModel.mbDataOnRows = nDataAxis == BIFF12_PTDEF_ROWAXIS;
1100  maDefModel.mbShowError = getFlag( nFlags2, BIFF12_PTDEF_SHOWERROR );
1101  maDefModel.mbShowMissing = getFlag( nFlags2, BIFF12_PTDEF_SHOWMISSING );
1102  maDefModel.mbShowItems = getFlag( nFlags1, BIFF12_PTDEF_SHOWITEMS );
1103  maDefModel.mbDisableFieldList = getFlag( nFlags1, BIFF12_PTDEF_DISABLEFIELDLIST );
1104  maDefModel.mbShowCalcMembers = !getFlag( nFlags1, BIFF12_PTDEF_HIDECALCMEMBERS );
1105  maDefModel.mbVisualTotals = !getFlag( nFlags1, BIFF12_PTDEF_WITHHIDDENTOTALS );
1106  maDefModel.mbShowDrill = !getFlag( nFlags1, BIFF12_PTDEF_HIDEDRILL );
1107  maDefModel.mbPrintDrill = getFlag( nFlags1, BIFF12_PTDEF_PRINTDRILL );
1108  maDefModel.mbEnableDrill = getFlag( nFlags2, BIFF12_PTDEF_ENABLEDRILL );
1109  maDefModel.mbPreserveFormatting = getFlag( nFlags2, BIFF12_PTDEF_PRESERVEFORMATTING );
1110  maDefModel.mbUseAutoFormat = getFlag( nFlags2, BIFF12_PTDEF_USEAUTOFORMAT );
1111  maDefModel.mbPageOverThenDown = getFlag( nFlags2, BIFF12_PTDEF_PAGEOVERTHENDOWN );
1112  maDefModel.mbSubtotalHiddenItems = getFlag( nFlags2, BIFF12_PTDEF_SUBTOTALHIDDENITEMS );
1113  maDefModel.mbRowGrandTotals = getFlag( nFlags2, BIFF12_PTDEF_ROWGRANDTOTALS );
1114  maDefModel.mbColGrandTotals = getFlag( nFlags2, BIFF12_PTDEF_COLGRANDTOTALS );
1115  maDefModel.mbFieldPrintTitles = getFlag( nFlags2, BIFF12_PTDEF_FIELDPRINTTITLES );
1116  maDefModel.mbItemPrintTitles = getFlag( nFlags2, BIFF12_PTDEF_ITEMPRINTTITLES );
1117  maDefModel.mbMergeItem = getFlag( nFlags2, BIFF12_PTDEF_MERGEITEM );
1118  maDefModel.mbApplyNumFmt = getFlag( nFlags2, BIFF12_PTDEF_APPLYNUMFMT );
1119  maDefModel.mbApplyFont = getFlag( nFlags2, BIFF12_PTDEF_APPLYFONT );
1120  maDefModel.mbApplyAlignment = getFlag( nFlags2, BIFF12_PTDEF_APPLYALIGNMENT );
1121  maDefModel.mbApplyBorder = getFlag( nFlags2, BIFF12_PTDEF_APPLYBORDER );
1122  maDefModel.mbApplyFill = getFlag( nFlags2, BIFF12_PTDEF_APPLYFILL );
1123  maDefModel.mbApplyProtection = getFlag( nFlags2, BIFF12_PTDEF_APPLYPROTECTION );
1124  maDefModel.mbShowEmptyRow = getFlag( nFlags2, BIFF12_PTDEF_SHOWEMPTYROW );
1125  maDefModel.mbShowEmptyCol = getFlag( nFlags2, BIFF12_PTDEF_SHOWEMPTYCOL );
1126  maDefModel.mbShowHeaders = !getFlag( nFlags1, BIFF12_PTDEF_HIDEHEADERS );
1127  maDefModel.mbFieldListSortAsc = getFlag( nFlags3, BIFF12_PTDEF_FIELDLISTSORTASC );
1128  maDefModel.mbCustomListSort = !getFlag( nFlags3, BIFF12_PTDEF_NOCUSTOMLISTSORT );
1129 }
1130 
1131 void PivotTable::importPTLocation( SequenceInputStream& rStrm, sal_Int16 nSheet )
1132 {
1133  BinRange aBinRange;
1134  rStrm >> aBinRange;
1141 }
1142 
1144 {
1145  importFields( maRowFields, rStrm );
1146 }
1147 
1149 {
1150  importFields( maColFields, rStrm );
1151 }
1152 
1154 {
1155  PTPageFieldModel aModel;
1156  sal_uInt8 nFlags;
1157  aModel.mnField = rStrm.readInt32();
1158  aModel.mnItem = rStrm.readInt32();
1159  rStrm.skip( 4 ); // hierarchy
1160  nFlags = rStrm.readuChar();
1161  if( getFlag( nFlags, BIFF12_PTPAGEFIELD_HASNAME ) )
1162  rStrm >> aModel.maName;
1163  maPageFields.push_back( aModel );
1164 }
1165 
1167 {
1168  PTDataFieldModel aModel;
1169  sal_Int32 nSubtotal, nShowDataAs;
1170  sal_uInt8 nHasName;
1171  aModel.mnField = rStrm.readInt32( );
1172  nSubtotal = rStrm.readInt32();
1173  nShowDataAs = rStrm.readInt32();
1174  aModel.mnBaseField = rStrm.readInt32();
1175  aModel.mnBaseItem = rStrm.readInt32();
1176  aModel.mnNumFmtId = rStrm.readInt32();
1177  nHasName = rStrm.readuChar();
1178  if( nHasName == 1 )
1179  rStrm >> aModel.maName;
1180  aModel.setBiffSubtotal( nSubtotal );
1181  aModel.setBiffShowDataAs( nShowDataAs );
1182  maDataFields.push_back( aModel );
1183 }
1184 
1186 {
1187  sal_Int32 nFieldIndex = static_cast< sal_Int32 >( maFields.size() );
1188  PivotTableFieldVector::value_type xTableField = std::make_shared<PivotTableField>( *this, nFieldIndex );
1189  maFields.push_back( xTableField );
1190  return *xTableField;
1191 }
1192 
1194 {
1195  PivotTableFilterVector::value_type xTableFilter = std::make_shared<PivotTableFilter>( *this );
1196  maFilters.push_back( xTableFilter );
1197  return *xTableFilter;
1198 }
1199 
1201 {
1202  if( getAddressConverter().validateCellRange( maLocationModel.maRange, true, true ) )
1203  {
1205  if( mpPivotCache && mpPivotCache->isValidDataSource() && !maDefModel.maName.isEmpty() )
1206  {
1207  // clear destination area of the original pivot table
1208  try
1209  {
1210  Reference< XSheetOperation > xSheetOp( getCellRangeFromDoc( maLocationModel.maRange ), UNO_QUERY_THROW );
1211  using namespace ::com::sun::star::sheet::CellFlags;
1212  xSheetOp->clearContents( VALUE | DATETIME | STRING | FORMULA | HARDATTR | STYLES | EDITATTR | FORMATTED );
1213  }
1214  catch( Exception& )
1215  {
1216  }
1217 
1218  try
1219  {
1220  // create a new data pilot descriptor based on the source data
1221  Reference< XDataPilotTablesSupplier > xDPTablesSupp( getSheetFromDoc( maLocationModel.maRange.aStart.Tab() ), UNO_QUERY_THROW );
1222  Reference< XDataPilotTables > xDPTables( xDPTablesSupp->getDataPilotTables(), UNO_SET_THROW );
1223  mxDPDescriptor.set( xDPTables->createDataPilotDescriptor(), UNO_SET_THROW );
1224  ScRange aRange = mpPivotCache->getSourceRange();
1225  CellRangeAddress aCellRangeAddress( aRange.aStart.Tab(),
1226  aRange.aStart.Col(), aRange.aStart.Row(),
1227  aRange.aEnd.Col(), aRange.aEnd.Row() );
1228  mxDPDescriptor->setSourceRange( aCellRangeAddress );
1229  mxDPDescriptor->setTag( maDefModel.maTag );
1230 
1231  // TODO: This is a hack. Eventually we need to convert the whole thing to the internal API.
1232  auto pImpl = comphelper::getUnoTunnelImplementation<ScDataPilotDescriptorBase>(mxDPDescriptor);
1233  if (!pImpl)
1234  return;
1235 
1236  mpDPObject = pImpl->GetDPObject();
1237  if (!mpDPObject)
1238  return;
1239 
1240  // global data pilot properties
1241  PropertySet aDescProp( mxDPDescriptor );
1242  aDescProp.setProperty( PROP_ColumnGrand, maDefModel.mbColGrandTotals );
1243  aDescProp.setProperty( PROP_RowGrand, maDefModel.mbRowGrandTotals );
1244  aDescProp.setProperty( PROP_ShowFilterButton, false );
1245  aDescProp.setProperty( PROP_DrillDownOnDoubleClick, maDefModel.mbEnableDrill );
1246 
1247  // finalize all fields, this finds field names and creates grouping fields
1249 
1250  // all row fields
1251  for( const auto& rRowField : maRowFields )
1252  if( PivotTableField* pField = getTableField( rRowField ) )
1253  pField->convertRowField();
1254 
1255  // all column fields
1256  for( const auto& rColField : maColFields )
1257  if( PivotTableField* pField = getTableField( rColField ) )
1258  pField->convertColField();
1259 
1260  // all page fields
1261  for( const auto& rPageField : maPageFields )
1262  if( PivotTableField* pField = getTableField( rPageField.mnField ) )
1263  pField->convertPageField( rPageField );
1264 
1265  // all hidden fields
1266  ::std::set< sal_Int32 > aVisFields;
1267  aVisFields.insert( maRowFields.begin(), maRowFields.end() );
1268  aVisFields.insert( maColFields.begin(), maColFields.end() );
1269  for( const auto& rPageField : maPageFields )
1270  aVisFields.insert( rPageField.mnField );
1271  sal_Int32 nIndex = 0;
1272  for( auto& rxField : maFields )
1273  {
1274  if( aVisFields.count( nIndex ) == 0 )
1275  rxField->convertHiddenField();
1276  ++nIndex;
1277  }
1278 
1279  // all data fields
1280  for( auto& rDataField : maDataFields )
1281  {
1282  if( const PivotCacheField* pCacheField = getCacheField( rDataField.mnField ) )
1283  {
1284  if ( pCacheField-> getGroupBaseField() != -1 )
1285  rDataField.mnField = pCacheField-> getGroupBaseField();
1286  }
1287  if( PivotTableField* pField = getTableField( rDataField.mnField ) )
1288  pField->convertDataField( rDataField );
1289  }
1290 
1291  // filters
1293 
1294  // calculate base position of table
1296  /* If page fields exist, include them into the destination
1297  area (they are excluded in Excel). Add an extra blank row. */
1298  if( !maPageFields.empty() )
1299  aPos.Row = ::std::max< sal_Int32 >( static_cast< sal_Int32 >( aPos.Row - maPageFields.size() - 1 ), 0 );
1300 
1301  // save interop grab bag
1303 
1304  // insert the DataPilot table into the sheet
1305  xDPTables->insertNewByName( maDefModel.maName, aPos, mxDPDescriptor );
1306  }
1307  catch( Exception& )
1308  {
1309  OSL_FAIL( "PivotTable::finalizeImport - exception while creating the DataPilot table" );
1310  }
1311  }
1312  }
1313 }
1314 
1316 {
1317  if (maFields.empty())
1318  return;
1319 
1320  /* Check whether group fields are already imported for another table
1321  sharing the same groups. */
1322  ScDPObject* pDPObj = getDPObject();
1323  const ScDocument& rDoc = getDocImport().getDoc();
1324  if (rDoc.HasPivotTable())
1325  {
1326  const ScDPCollection* pDPCollection = rDoc.GetDPCollection();
1327  assert(pDPCollection != nullptr);
1328  const ScDPDimensionSaveData* pGroups = nullptr;
1329  bool bRefFound = pDPCollection->GetReferenceGroups(*pDPObj, &pGroups);
1330  // Apply reference groups on this table.
1331  if (bRefFound && pGroups && pGroups->HasGroupDimensions()) {
1332  ScDPSaveData* pSaveData = pDPObj->GetSaveData();
1333  if (pSaveData) {
1334  pSaveData->SetDimensionData(pGroups);
1335  pDPObj->ReloadGroupTableData();
1337  return;
1338  }
1339 
1340  }
1341  }
1343 }
1344 
1345 void PivotTable::finalizeDateGroupingImport( const Reference< XDataPilotField >& rxBaseDPField, sal_Int32 nBaseFieldIdx )
1346 {
1347  // process all fields, there is no chaining information in the cache fields
1348  maFields.forEachMem( &PivotTableField::finalizeDateGroupingImport, ::std::cref(rxBaseDPField), nBaseFieldIdx );
1349 }
1350 
1351 void PivotTable::finalizeParentGroupingImport( const Reference< XDataPilotField >& rxBaseDPField,
1352  const PivotCacheField& rBaseCacheField, PivotCacheGroupItemVector& orItemNames )
1353 {
1354  // try to create parent group fields that group the items of the passed base field
1355  if( PivotTableField* pParentTableField = maFields.get( rBaseCacheField.getParentGroupField() ).get() )
1356  pParentTableField->finalizeParentGroupingImport( rxBaseDPField, rBaseCacheField, orItemNames );
1357 }
1358 
1359 Reference< XDataPilotField > PivotTable::getDataPilotField( const OUString& rFieldName ) const
1360 {
1361  Reference< XDataPilotField > xDPField;
1362  if( !rFieldName.isEmpty() && mxDPDescriptor.is() ) try
1363  {
1364  Reference< XNameAccess > xDPFieldsNA( mxDPDescriptor->getDataPilotFields(), UNO_QUERY_THROW );
1365  xDPField.set( xDPFieldsNA->getByName( rFieldName ), UNO_QUERY );
1366  }
1367  catch( Exception& )
1368  {
1369  }
1370  return xDPField;
1371 }
1372 
1373 Reference< XDataPilotField > PivotTable::getDataPilotField( sal_Int32 nFieldIdx ) const
1374 {
1375  Reference< XDataPilotField > xDPField;
1376  if( const PivotTableField* pTableField = maFields.get( nFieldIdx ).get() )
1377  xDPField = getDataPilotField( pTableField->getDPFieldName() );
1378  return xDPField;
1379 }
1380 
1381 Reference< XDataPilotField > PivotTable::getDataLayoutField() const
1382 {
1383  Reference< XDataPilotField > xDPField;
1384  try
1385  {
1386  Reference< XDataPilotDataLayoutFieldSupplier > xDPDataFieldSupp( mxDPDescriptor, UNO_QUERY_THROW );
1387  xDPField = xDPDataFieldSupp->getDataLayoutField();
1388  }
1389  catch( Exception& )
1390  {
1391  }
1392  return xDPField;
1393 }
1394 
1396 {
1397  return mpPivotCache ? mpPivotCache->getCacheField( nFieldIdx ) : nullptr;
1398 }
1399 
1400 const PivotCacheField* PivotTable::getCacheField( sal_Int32 nFieldIdx ) const
1401 {
1402  return mpPivotCache ? mpPivotCache->getCacheField( nFieldIdx ) : nullptr;
1403 }
1404 
1405 const PivotCacheField* PivotTable::getCacheFieldOfDataField( sal_Int32 nDataItemIdx ) const
1406 {
1407  const PTDataFieldModel* pDataField = ContainerHelper::getVectorElement( maDataFields, nDataItemIdx );
1408  return pDataField ? getCacheField( pDataField->mnField ) : nullptr;
1409 }
1410 
1411 sal_Int32 PivotTable::getCacheDatabaseIndex( sal_Int32 nFieldIdx ) const
1412 {
1413  return mpPivotCache ? mpPivotCache->getCacheDatabaseIndex( nFieldIdx ) : -1;
1414 }
1415 
1416 // private --------------------------------------------------------------------
1417 
1419 {
1420  return (nFieldIdx == OOX_PT_DATALAYOUTFIELD) ? &maDataField : maFields.get( nFieldIdx ).get();
1421 }
1422 
1423 void PivotTable::importField( IndexVector& orFields, const AttributeList& rAttribs )
1424 {
1425  orFields.push_back( rAttribs.getInteger( XML_x, -1 ) );
1426 }
1427 
1429 {
1430  OSL_ENSURE( orFields.empty(), "PivotTable::importFields - multiple record instances" );
1431  orFields.clear();
1432  sal_Int32 nCount = rStrm.readInt32();
1433  OSL_ENSURE( 4 * nCount == rStrm.getRemaining(), "PivotTable::importFields - invalid field count" );
1434  nCount = static_cast< sal_Int32 >( rStrm.getRemaining() / 4 );
1435  for( sal_Int32 nIdx = 0; nIdx < nCount; ++nIdx )
1436  orFields.push_back( rStrm.readInt32() );
1437 }
1438 
1440  WorkbookHelper( rHelper )
1441 {
1442 }
1443 
1445 {
1446  PivotTableVector::value_type xTable = std::make_shared<PivotTable>( *this );
1447  maTables.push_back( xTable );
1448  return *xTable;
1449 }
1450 
1452 {
1454 }
1455 
1456 } // namespace oox
1457 
1458 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
sal_Int32 mnEvalOrder
Filter type.
bool mbApplyAlignment
True = apply font from autoformatting.
Helper class to provide access to global workbook data.
void convertHiddenField()
Converts dimension and other settings for a hidden field.
void setBiffType(sal_uInt16 nType)
Sets item type for BIFF import.
::std::vector< IdCaptionPair > IdCaptionPairList
bool mbProductSubtotal
True = show minimum subtotals.
void finalizeImport()
Inserts the pivot table into the sheet.
STRING
void ReloadGroupTableData()
Definition: dpobject.cxx:810
sal_Int32 nIndex
bool mbTopFilter
Hierarchy for filter calculation.
std::map< OUString, css::uno::Any > maInteropGrabBag
Descriptor of the DataPilot object.
ScAddress aStart
Definition: address.hxx:500
PivotCache * mpPivotCache
Location settings of the pivot table.
ScDocumentImport & getDocImport()
ItemModelVector maItems
The parent pivot table object.
bool mbMultiPageItems
True = auto show filter shows top entries, false = bottom.
virtual void skip(sal_Int32 nBytes, size_t nAtomSize=1) override
This class has to do with handling exclusively grouped dimensions? TODO: Find out what this class doe...
Definition: dpdimsave.hxx:160
ScDPSaveMember * GetMemberByName(const OUString &rName)
Get a member object by its name.
Definition: dpsave.cxx:456
OptValue< bool > getBool(sal_Int32 nAttrToken) const
SCROW Row() const
Definition: address.hxx:262
ScDPObject * getDPObject()
bool mbTopAutoShow
True = auto show (top 10) filter enabled.
static const VectorType::value_type * getVectorElement(const VectorType &rVector, sal_Int32 nIndex)
bool HasGroupDimensions() const
Definition: dpdimsave.cxx:694
sal_Int32 mnField
Unique name of the page field.
OptValue< OUString > getXString(sal_Int32 nAttrToken) const
sal_Int32 mnNumFmtId
OptValue< sal_Int32 > getInteger(sal_Int32 nAttrToken) const
void finalizeParentGroupingImport(const css::uno::Reference< css::sheet::XDataPilotField > &rxBaseDPField, const PivotCacheField &rBaseCacheField, PivotCacheGroupItemVector &orItemNames)
Finalizes the grouped field after import.
void finalizeImport()
Inserts all pivot tables into the sheet.
SC_DLLPUBLIC bool GetReferenceGroups(const ScDPObject &rDPObj, const ScDPDimensionSaveData **pGroups) const
Definition: dpobject.cxx:3523
sal_Int32 mnMeasureField
Unique identifier.
sal_Int32 mnSortRefItem
Reference field for autosorting.
A 2D cell range address struct for binary filters.
PTFilterModel()
True = filter shows top entries, false = bottom.
SC_DLLPUBLIC ScDPCollection * GetDPCollection()
Definition: documen3.cxx:346
bool mbStdDevPSubtotal
True = show standard deviation subtotals.
void importRowField(const AttributeList &rAttribs)
Reads the index of a field located in the row dimension.
void importPTReferenceItem(SequenceInputStream &rStrm)
Imports pivot field item reference settings from the PTREFERENCEITEM record.
value_type get(sal_Int32 nIndex) const
void PutInteropGrabBag(std::map< OUString, css::uno::Any > &&val)
Definition: dpobject.hxx:262
ScAddress aEnd
Definition: address.hxx:501
const ScRange & getSourceRange() const
Returns the internal cell range the cache is based on.
OptValue< double > getDouble(sal_Int32 nAttrToken) const
css::uno::Reference< css::table::XCellRange > getCellRangeFromDoc(const ScRange &rRange) const
Returns the XCellRange interface for the passed cell range address.
sal_Int32 mnFieldIndex
Name of the field in DataPilot field collection.
sal_uInt32 readuInt32()
#define STATIC_ARRAY_SELECT(array, index, def)
OUString maStrValue2
First string value for label filter.
sal_Int32 mnFirstDataCol
First row of data cells (relative in pivot table).
::std::vector< sal_Int32 > IndexVector
OptValue< OUString > getString(sal_Int32 nAttrToken) const
unsigned char readuChar()
sal_uInt16 mnId
void finalizeDateGroupingImport(const css::uno::Reference< css::sheet::XDataPilotField > &rxBaseDPField, sal_Int32 nBaseFieldIdx)
Creates all date group fields for the specified cache field after import.
static bool convertToCellRangeUnchecked(ScRange &orRange, const OUString &rString, sal_Int16 nSheet)
Converts the passed string to a cell range address, without checking any sheet limits.
SC_DLLPUBLIC void SetIsVisible(bool bSet)
Definition: dpsave.cxx:95
const PivotTable & mrPivotTable
WorkbookSettings & getWorkbookSettings() const
Returns the global workbook settings object.
void importColField(const AttributeList &rAttribs)
Reads the index of a field located in the column dimension.
css::uno::Reference< css::sheet::XDataPilotField > convertRowColPageField(sal_Int32 nAxis)
Converts dimension and other settings for row, column, page, or hidden fields.
sal_Int32 getCacheDatabaseIndex(sal_Int32 nFieldIdx) const
Returns the source column index of the field with the passed index.
#define SAL_MAX_UINT32
void importDataField(const AttributeList &rAttribs)
Reads the settings of a field located in the data dimension from the dataField element.
void forEachMem(FuncType pFunc) const
void importPTFItem(SequenceInputStream &rStrm)
Imports settings of an item in this pivot field from the PTFITEM record.
bool mbOutline
True = show items without data.
sal_Int32 mnItem
Base pivot field.
sal_uInt16 readuInt16()
sal_Int32 mnSubtotal
Base pivot field.
PTFieldModel()
True = multiple items selectable in page dimension.
static void importFields(IndexVector &orFields, SequenceInputStream &rStrm)
Reads an array of field indexes for the row or column dimension.
sal_Int32 mnFirstDataRow
First row of header cells (relative in pivot table).
void importLocation(const AttributeList &rAttribs, sal_Int16 nSheet)
Reads the location of the pivot table from the location element.
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
int nCount
sal_Int32 mnColPageCount
Number of rows in page filter area.
void finalizeImport(const css::uno::Reference< css::sheet::XDataPilotDescriptor > &rxDPDesc)
Finalizes the field after import, creates grouping and other settings.
PivotCacheBuffer & getPivotCaches() const
Returns the collection of pivot caches.
SCTAB Tab() const
Definition: address.hxx:271
css::uno::Reference< css::sheet::XDataPilotDescriptor > mxDPDescriptor
The pivot cache this table is based on.
sal_Int32 mnField
Number of items or percent or sum to be shown.
void setBiffSubtotal(sal_Int32 nSubtotal)
Sets the subtotal aggregation function for BIFF import.
void setBiffShowDataAs(sal_Int32 nShowDataAs)
Sets the 'show data as' type for BIFF import.
void importTop10Filter(SequenceInputStream &rStrm)
Reads additional settings of a field filter from the TOP10FILTER record.
void finalizeFieldsImport()
Finalizes all fields, finds field names and creates grouping fields.
OptValue< sal_uInt32 > getUnsigned(sal_Int32 nAttrToken) const
bool mbHidden
True = show item details (items of child fields).
bool getFlag(Type nBitField, Type nMask)
bool mbInsertBlankRow
True = show subtotals on top of items in outline or compact mode.
void importPivotTableDefinition(const AttributeList &rAttribs)
Reads global pivot table settings from the pivotTableDefinition element.
void importPageField(const AttributeList &rAttribs)
Reads the settings of a field located in the page dimension from the pageField element.
bool mbInsertPageBreak
True = insert blank rows after items.
bool mbCountASubtotal
True = show sum subtotals.
bool mbDataField
Item in reference field for autosorting.
sal_Int32 getCacheDatabaseIndex(sal_Int32 nFieldIdx) const
Returns the source column index of the pivot field with the passed index, or -1.
double mfValue
Second string value for label filter.
void importPTPageField(SequenceInputStream &rStrm)
Reads the settings of a field located in the page dimension from the PTPAGEFIELD record.
sal_Int32 mnFirstHeaderRow
Target cell range for the pivot table.
const PPTXLayoutInfo aLayoutInfo[LAYOUT_SIZE]
PTFieldItemModel()
True = item is hidden.
#define SAL_MAX_INT32
IndexVector maRowFields
Data layout field.
SC_DLLPUBLIC void SetDimensionData(const ScDPDimensionSaveData *pNew)
Definition: dpsave.cxx:1203
SC_DLLPUBLIC bool HasPivotTable() const
Definition: documen3.cxx:341
void importFilter(const AttributeList &rAttribs)
Reads the settings of a field filter from the filter element.
container_type::value_type value_type
sal_Int32 mnType
bool mbAutoShow
True = insert page breaks after items.
PTLocationModel maLocationModel
Global pivot table settings.
static void importField(IndexVector &orFields, const AttributeList &rAttribs)
Reads a field index for the row or column dimension.
bool mbApplyFill
True = apply border from autoformatting.
bool mbApplyProtection
True = apply fill from autoformatting.
PivotTableFieldVector maFields
const PivotCacheField * getCacheFieldOfDataField(sal_Int32 nDataItemIdx) const
Returns the base cache field of the data field item with the specified index.
PivotTable(const WorkbookHelper &rHelper)
XML_TOKEN_INVALID
void finalizeImport()
Applies the filter to the associated pivot table field if possible.
sal_Int32 mnShowDataAs
Subtotal aggregation function.
ScDPSaveData * GetSaveData() const
Definition: dpobject.hxx:141
sal_Int32 mnNumFmtId
Base item for 'show data as'.
bool mbSubtotalTop
True = show in outline view, false = show in tabular view.
void putToInteropGrabBag(const OUString &sName, const AttributeList &rAttribs)
Puts the attributes to the named grab bag value.
void importPTRowFields(SequenceInputStream &rStrm)
Reads the indexes of all fields located in the row dimension from a PTROWFIELDS record.
bool mbShowAll
True = show variance of population subtotals.
SCCOL Col() const
Definition: address.hxx:267
sal_Int32 mnAutoShowRankBy
Number of items (or percent/sum) to be shown in auto show filter.
css::uno::Reference< css::sheet::XDataPilotField > getDataPilotField(const OUString &rFieldName) const
Returns the associated data pilot field for the specified pivot table field.
sal_Int32 mnType
Member property field.
void finalizeParentGroupingImport(const css::uno::Reference< css::sheet::XDataPilotField > &rxBaseDPField, const PivotCacheField &rBaseCacheField, PivotCacheGroupItemVector &orItemNames)
Creates all grouped fields for the specified cache field after import.
void importPTDefinition(SequenceInputStream &rStrm)
Reads global pivot table settings from the PTDEFINITION record.
void convertPageField(const PTPageFieldModel &rPageField)
Converts dimension and other settings for a page field.
SC_DLLPUBLIC void SetShowDetails(bool bSet)
Definition: dpsave.cxx:105
void setBiffAxis(sal_uInt8 nAxisFlags)
Sets axis type for BIFF import.
bool mbApplyBorder
True = apply alignment from autoformatting.
css::uno::Reference< css::sheet::XDataPilotField > getDataLayoutField() const
Returns the data layout field used to store all data fields in row/col dimension. ...
bool mbStdDevSubtotal
True = show count numbers subtotals.
bool mbMaxSubtotal
True = show average subtotals.
OUString maDPFieldName
Pivot field settings.
PTPageFieldModel()
Index of field item that is shown by the page field.
PivotTableField & createTableField()
Creates and returns a new pivot table field.
void importPTLocation(SequenceInputStream &rStrm, sal_Int16 nSheet)
Reads the location of the pivot table from the PTLOCATION record.
void importPTDataField(SequenceInputStream &rStrm)
Reads the settings of a field located in the data dimension from the PTDATAFIELD record.
sal_Int64 getRemaining() const
bool mbVarSubtotal
True = show standard deviation of population subtotals.
PivotTableFilterVector maFilters
Settings for all fields in data area.
void convertDataField(const PTDataFieldModel &rDataField)
Converts dimension and other settings for a data field.
sal_Int32 mnMeasureHier
Data field for filter calculation.
DataFieldVector maDataFields
Settings for all fields in page dimension.
sal_Int32 mnBaseField
Show data as, based on another field.
void importPTField(SequenceInputStream &rStrm)
Imports pivot field settings from the PTFIELD record.
PivotCacheField * getCacheField(sal_Int32 nFieldIdx)
Returns the cache field with the specified index.
void importTop10(const AttributeList &rAttribs)
Reads additional settings of a field filter from the top10 element.
#define SAL_WARN_IF(condition, area, stream)
unsigned char sal_uInt8
bool mbShowDetails
User caption of the item.
sal_Int32 mnSortType
Index of the data field auto show filter is based on.
sal_Int32 mnNumFmtId
Axis this field is assigned to (none, row, column, page).
PivotTableField maDataField
All pivot table fields.
OUString msCaption
Type of the item.
void importItem(const AttributeList &rAttribs)
Imports settings of an item in this pivot field from the item element.
sal_Int32 mnRowPageCount
First column of data cells (relative in pivot table).
void convertColField()
Converts dimension and other settings for a column field.
void importReferenceItem(const AttributeList &rAttribs)
Imports pivot field item reference settings from the x element.
PTDefinitionModel maDefModel
All field filters.
const css::uno::Reference< css::xml::sax::XFastAttributeList > & getFastAttributeList() const
bool mbVarPSubtotal
True = show variance subtotals.
QPRO_FUNC_TYPE nType
Definition: qproform.cxx:401
bool mbSumSubtotal
True = show default subtotals.
bool isValidDataSource() const
Returns true, if the pivot cache is based on a valid data source, so that pivot tables can be created...
PivotTable & createPivotTable()
Creates and returns a new pivot table.
OUString maStrValue1
Description of the field filter.
sal_Int32 mnAutoShowItems
Number format for field items.
bool mbApplyFont
True = apply number format from autoformatting.
static css::uno::Sequence< typename VectorType::value_type > vectorToSequence(const VectorType &rVector)
IndexVector maColFields
Indexes to fields in row dimension.
OUString getFormattedName(const ScDPSaveDimension &rSaveDim, ScDPObject *pObj, const DateTime &rNullDate) const
Returns the string representation of the item, using the actual formatting.
PivotCacheField * getCacheField(sal_Int32 nFieldIdx)
Returns the cache field with the specified index.
css::uno::Reference< css::sheet::XSpreadsheet > getSheetFromDoc(sal_Int32 nSheet) const
Returns a reference to the specified spreadsheet in the document model.
sal_Int32 mnId
Evaluation order index.
void importReference(const AttributeList &rAttribs)
Imports pivot field reference settings from the reference element.
sal_Int32 mnMemPropField
Base pivot field.
sal_Int32 mnSortRefField
Autosorting type.
void finalizeDateGroupingImport(const css::uno::Reference< css::sheet::XDataPilotField > &rxBaseDPField, sal_Int32 nBaseFieldIdx)
Finalizes the grouped date field after import.
sal_Int32 mnField
Name of the data field.
PTDataFieldModel()
Number format for the result.
PivotTableBuffer(const WorkbookHelper &rHelper)
bool mbAverageSubtotal
True = show count all subtotals.
PivotTableFilter & createTableFilter()
Creates and returns a new pivot table filter.
void finalizeImportBasedOnCache(const css::uno::Reference< css::sheet::XDataPilotDescriptor > &rxDPDesc)
bool mbApplyNumFmt
Index of predefined autoformatting.
PivotTableField * getTableField(sal_Int32 nFieldIdx)
Returns a pivot table field by its index.
void importPTReference(SequenceInputStream &rStrm)
Imports pivot field reference settings from the PTREFERENCE record.
void importPTFilter(SequenceInputStream &rStrm)
Reads the settings of a field filter from the PTFILTER record.
void importPivotField(const AttributeList &rAttribs)
Imports pivot field settings from the pivotField element.
bool mbCountSubtotal
True = show product subtotals.
PageFieldVector maPageFields
Indexes to fields in column dimension.
SC_DLLPUBLIC ScDPSaveDimension * GetDimensionByName(const OUString &rName)
Get a dimension object by its name.
Definition: dpsave.cxx:835
PTFieldModel maModel
All items of this field.
sal_Int32 mnBaseItem
Base field for 'show data as'.
OUString maDescription
Name of the field filter.
bool setProperty(sal_Int32 nPropId, const Type &rValue)
sal_Int32 getParentGroupField() const
Returns the index of the parent group field that groups the items of this field.
void convertRowField()
Converts dimension and other settings for a row field.
PTLocationModel()
Number of columns in page filter area.
bool mbMinSubtotal
True = show maximum subtotals.
PivotTableField(PivotTable &rPivotTable, sal_Int32 nFieldIndex)
OptValue< sal_Int32 > getToken(sal_Int32 nAttrToken) const
void importPTColFields(SequenceInputStream &rStrm)
Reads the indexes of all fields located in the column dimension from a PTCOLFIELDS record...
AddressConverter & getAddressConverter() const
Returns the converter for string to cell address/range conversion.
::std::vector< PivotCacheGroupItem > PivotCacheGroupItemVector
bool mbDefaultSubtotal
True = field appears in data area.
PivotCache * importPivotCacheFragment(sal_Int32 nCacheId)
Imports and stores a pivot cache definition fragment on first call, returns the imported cache on sub...
PivotTableFilter(const PivotTable &rPivotTable)
const OUString & getName() const
Returns the name of the cache field.
ScDocument & getDoc()
sal_Int32 mnType
Index to shared item in pivot cache.