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 
42 #include <comphelper/sequence.hxx>
43 #include <osl/diagnose.h>
44 #include <tools/diagnose_ex.h>
45 #include <sal/log.hxx>
50 #include <oox/token/properties.hxx>
51 #include <oox/token/tokens.hxx>
52 #include <addressconverter.hxx>
53 #include <biffhelper.hxx>
54 
55 #include <dapiuno.hxx>
56 #include <dpobject.hxx>
57 #include <dpsave.hxx>
58 #include <dpdimsave.hxx>
59 #include <document.hxx>
60 #include <documentimport.hxx>
61 #include <workbooksettings.hxx>
62 
63 namespace oox::xls {
64 
65 using namespace ::com::sun::star::container;
66 using namespace ::com::sun::star::sheet;
67 using namespace ::com::sun::star::table;
68 using namespace ::com::sun::star::uno;
69 
70 namespace {
71 
72 const sal_Int32 OOX_PT_DATALAYOUTFIELD = -2;
73 
74 const sal_Int32 OOX_PT_PREVIOUS_ITEM = 0x001000FC;
75 const sal_Int32 OOX_PT_NEXT_ITEM = 0x001000FD;
76 
77 const sal_uInt32 BIFF12_PTFIELD_DATAFIELD = 0x00000008;
78 const sal_uInt32 BIFF12_PTFIELD_DEFAULT = 0x00000100;
79 const sal_uInt32 BIFF12_PTFIELD_SUM = 0x00000200;
80 const sal_uInt32 BIFF12_PTFIELD_COUNTA = 0x00000400;
81 const sal_uInt32 BIFF12_PTFIELD_AVERAGE = 0x00000800;
82 const sal_uInt32 BIFF12_PTFIELD_MAX = 0x00001000;
83 const sal_uInt32 BIFF12_PTFIELD_MIN = 0x00002000;
84 const sal_uInt32 BIFF12_PTFIELD_PRODUCT = 0x00004000;
85 const sal_uInt32 BIFF12_PTFIELD_COUNT = 0x00008000;
86 const sal_uInt32 BIFF12_PTFIELD_STDDEV = 0x00010000;
87 const sal_uInt32 BIFF12_PTFIELD_STDDEVP = 0x00020000;
88 const sal_uInt32 BIFF12_PTFIELD_VAR = 0x00040000;
89 const sal_uInt32 BIFF12_PTFIELD_VARP = 0x00080000;
90 
91 const sal_uInt32 BIFF12_PTFIELD_SHOWALL = 0x00000020;
92 const sal_uInt32 BIFF12_PTFIELD_OUTLINE = 0x00000040;
93 const sal_uInt32 BIFF12_PTFIELD_INSERTBLANKROW = 0x00000080;
94 const sal_uInt32 BIFF12_PTFIELD_SUBTOTALTOP = 0x00000100;
95 const sal_uInt32 BIFF12_PTFIELD_INSERTPAGEBREAK = 0x00000800;
96 const sal_uInt32 BIFF12_PTFIELD_AUTOSORT = 0x00001000;
97 const sal_uInt32 BIFF12_PTFIELD_SORTASCENDING = 0x00002000;
98 const sal_uInt32 BIFF12_PTFIELD_AUTOSHOW = 0x00004000;
99 const sal_uInt32 BIFF12_PTFIELD_AUTOSHOWTOP = 0x00008000;
100 const sal_uInt32 BIFF12_PTFIELD_MULTIPAGEITEMS = 0x00080000;
101 
102 const sal_uInt16 BIFF12_PTFITEM_HIDDEN = 0x0001;
103 const sal_uInt16 BIFF12_PTFITEM_HIDEDETAILS = 0x0002;
104 
105 const sal_uInt8 BIFF12_PTPAGEFIELD_HASNAME = 0x01;
106 const sal_Int32 BIFF12_PTPAGEFIELD_MULTIITEMS = 0x001000FE;
107 
108 const sal_uInt16 BIFF12_PTFILTER_HASNAME = 0x0001;
109 const sal_uInt16 BIFF12_PTFILTER_HASDESCRIPTION = 0x0002;
110 const sal_uInt16 BIFF12_PTFILTER_HASSTRVALUE1 = 0x0004;
111 const sal_uInt16 BIFF12_PTFILTER_HASSTRVALUE2 = 0x0008;
112 
113 const sal_uInt8 BIFF12_TOP10FILTER_TOP = 0x01;
114 const sal_uInt8 BIFF12_TOP10FILTER_PERCENT = 0x02;
115 
116 const sal_uInt32 BIFF12_PTDEF_SHOWITEMS = 0x00000100;
117 const sal_uInt32 BIFF12_PTDEF_DISABLEFIELDLIST = 0x00000400;
118 const sal_uInt32 BIFF12_PTDEF_HIDECALCMEMBERS = 0x00001000;
119 const sal_uInt32 BIFF12_PTDEF_WITHHIDDENTOTALS = 0x00002000;
120 const sal_uInt32 BIFF12_PTDEF_HIDEDRILL = 0x00100000;
121 const sal_uInt32 BIFF12_PTDEF_PRINTDRILL = 0x00200000;
122 const sal_uInt32 BIFF12_PTDEF_HIDEHEADERS = 0x80000000;
123 
124 const sal_uInt32 BIFF12_PTDEF_SHOWEMPTYROW = 0x00000004;
125 const sal_uInt32 BIFF12_PTDEF_SHOWEMPTYCOL = 0x00000008;
126 const sal_uInt32 BIFF12_PTDEF_ENABLEDRILL = 0x00000020;
127 const sal_uInt32 BIFF12_PTDEF_PRESERVEFORMATTING = 0x00000080;
128 const sal_uInt32 BIFF12_PTDEF_USEAUTOFORMAT = 0x00000100;
129 const sal_uInt32 BIFF12_PTDEF_SHOWERROR = 0x00000200;
130 const sal_uInt32 BIFF12_PTDEF_SHOWMISSING = 0x00000400;
131 const sal_uInt32 BIFF12_PTDEF_PAGEOVERTHENDOWN = 0x00000800;
132 const sal_uInt32 BIFF12_PTDEF_SUBTOTALHIDDENITEMS = 0x00001000;
133 const sal_uInt32 BIFF12_PTDEF_ROWGRANDTOTALS = 0x00002000;
134 const sal_uInt32 BIFF12_PTDEF_COLGRANDTOTALS = 0x00004000;
135 const sal_uInt32 BIFF12_PTDEF_FIELDPRINTTITLES = 0x00008000;
136 const sal_uInt32 BIFF12_PTDEF_ITEMPRINTTITLES = 0x00020000;
137 const sal_uInt32 BIFF12_PTDEF_MERGEITEM = 0x00040000;
138 const sal_uInt32 BIFF12_PTDEF_HASDATACAPTION = 0x00080000;
139 const sal_uInt32 BIFF12_PTDEF_HASGRANDTOTALCAPTION = 0x00100000;
140 const sal_uInt32 BIFF12_PTDEF_HASPAGESTYLE = 0x00200000;
141 const sal_uInt32 BIFF12_PTDEF_HASPIVOTTABLESTYLE = 0x00400000;
142 const sal_uInt32 BIFF12_PTDEF_HASVACATEDSTYLE = 0x00800000;
143 const sal_uInt32 BIFF12_PTDEF_APPLYNUMFMT = 0x01000000;
144 const sal_uInt32 BIFF12_PTDEF_APPLYFONT = 0x02000000;
145 const sal_uInt32 BIFF12_PTDEF_APPLYALIGNMENT = 0x04000000;
146 const sal_uInt32 BIFF12_PTDEF_APPLYBORDER = 0x08000000;
147 const sal_uInt32 BIFF12_PTDEF_APPLYFILL = 0x10000000;
148 const sal_uInt32 BIFF12_PTDEF_APPLYPROTECTION = 0x20000000;
149 const sal_uInt32 BIFF12_PTDEF_HASTAG = 0x40000000;
150 
151 const sal_uInt32 BIFF12_PTDEF_NOERRORCAPTION = 0x00000040;
152 const sal_uInt32 BIFF12_PTDEF_NOMISSINGCAPTION = 0x00000080;
153 const sal_uInt32 BIFF12_PTDEF_HASROWHEADERCAPTION = 0x00000400;
154 const sal_uInt32 BIFF12_PTDEF_HASCOLHEADERCAPTION = 0x00000800;
155 const sal_uInt32 BIFF12_PTDEF_FIELDLISTSORTASC = 0x00001000;
156 const sal_uInt32 BIFF12_PTDEF_NOCUSTOMLISTSORT = 0x00004000;
157 
158 const sal_uInt8 BIFF12_PTDEF_ROWAXIS = 1;
159 const sal_uInt8 BIFF12_PTDEF_COLAXIS = 2;
160 
161 } // namespace
162 
164  mnCacheItem( -1 ),
165  mnType( XML_data ),
166  mbShowDetails( true ),
167  mbHidden( false )
168 {
169 }
170 
172 {
173  static const sal_Int32 spnTypes[] = { XML_data, XML_default,
174  XML_sum, XML_countA, XML_avg, XML_max, XML_min, XML_product, XML_count,
175  XML_stdDev, XML_stdDevP, XML_var, XML_varP, XML_grand, XML_blank };
176  mnType = STATIC_ARRAY_SELECT( spnTypes, nType, XML_data );
177 }
178 
180  mnAxis( XML_TOKEN_INVALID ),
181  mnNumFmtId( 0 ),
182  mnAutoShowItems( 10 ),
183  mnAutoShowRankBy( -1 ),
184  mnSortType( XML_manual ),
185  mnSortRefField( -1 ),
186  mnSortRefItem( -1 ),
187  mbDataField( false ),
188  mbDefaultSubtotal( true ),
189  mbSumSubtotal( false ),
190  mbCountASubtotal( false ),
191  mbAverageSubtotal( false ),
192  mbMaxSubtotal( false ),
193  mbMinSubtotal( false ),
194  mbProductSubtotal( false ),
195  mbCountSubtotal( false ),
196  mbStdDevSubtotal( false ),
197  mbStdDevPSubtotal( false ),
198  mbVarSubtotal( false ),
199  mbVarPSubtotal( false ),
200  mbShowAll( true ),
201  mbOutline( true ),
202  mbSubtotalTop( true ),
203  mbInsertBlankRow( false ),
204  mbInsertPageBreak( false ),
205  mbAutoShow( false ),
206  mbTopAutoShow( true ),
207  mbMultiPageItems( false )
208 {
209 }
210 
212 {
213  /* Weird. The axis field is organized as bit field, but only one of the
214  row/col/page flags are allowed at the same time and refer to the values
215  'axisRow', 'axisCol', and 'axisPage' of the XML attribute
216  'pivotField@axis'. Additionally, the fourth bit determines if the field
217  is a data field, which may appear combined with the row/col/page flags.
218  Therefore, this bit is unrelated to the 'axisValues' value of the
219  'pivotField@axis' attribute, but refers to the 'pivotField@dataField'
220  boolean attribute. */
221  static const sal_Int32 spnAxisIds[] = { XML_TOKEN_INVALID, XML_axisRow, XML_axisCol, XML_TOKEN_INVALID, XML_axisPage };
222  mnAxis = STATIC_ARRAY_SELECT( spnAxisIds, nAxis, XML_TOKEN_INVALID );
223 }
224 
226  mnField( -1 ),
227  mnItem( BIFF12_PTPAGEFIELD_MULTIITEMS )
228 {
229 }
230 
232  mnField( -1 ),
233  mnSubtotal( XML_sum ),
234  mnShowDataAs( XML_normal ),
235  mnBaseField( -1 ),
236  mnBaseItem( -1 ),
237  mnNumFmtId( 0 )
238 {
239 }
240 
241 void PTDataFieldModel::setBiffSubtotal( sal_Int32 nSubtotal )
242 {
243  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 };
244  mnSubtotal = STATIC_ARRAY_SELECT( spnSubtotals, nSubtotal, XML_TOKEN_INVALID );
245 }
246 
247 void PTDataFieldModel::setBiffShowDataAs( sal_Int32 nShowDataAs )
248 {
249  static const sal_Int32 spnShowDataAs[] = { XML_normal, XML_difference, XML_percent, XML_percentDiff, XML_runTotal, XML_percentOfRow, XML_percentOfCol, XML_percentOfTotal, XML_index };
250  mnShowDataAs = STATIC_ARRAY_SELECT( spnShowDataAs, nShowDataAs, XML_TOKEN_INVALID );
251 }
252 
253 PivotTableField::PivotTableField( PivotTable& rPivotTable, sal_Int32 nFieldIndex ) :
254  WorkbookHelper( rPivotTable ),
255  mrPivotTable( rPivotTable ),
256  mnFieldIndex( nFieldIndex )
257 {
258 }
259 
261 {
262  /* The documentation mentions a value 'axisValues' for the attribute
263  'pivotField@axis'. But this value is not used to mark a data field, as
264  data fields may be inserted in one of the row/column/page dimensions at
265  the same time. Therefore, the boolean attribute 'pivotField@dataField'
266  is really used to mark data fields. */
267  maModel.mnAxis = rAttribs.getToken( XML_axis, XML_TOKEN_INVALID );
268  maModel.mnNumFmtId = rAttribs.getInteger( XML_numFmtId, 0 );
269  maModel.mnAutoShowItems = rAttribs.getInteger( XML_itemPageCount, 10 );
270  maModel.mnAutoShowRankBy = rAttribs.getInteger( XML_rankBy, -1 );
271  maModel.mnSortType = rAttribs.getToken( XML_sortType, XML_manual );
272  maModel.mbDataField = rAttribs.getBool( XML_dataField, false );
273  maModel.mbDefaultSubtotal = rAttribs.getBool( XML_defaultSubtotal, true );
274  maModel.mbSumSubtotal = rAttribs.getBool( XML_sumSubtotal, false );
275  maModel.mbCountASubtotal = rAttribs.getBool( XML_countASubtotal, false );
276  maModel.mbAverageSubtotal = rAttribs.getBool( XML_avgSubtotal, false );
277  maModel.mbMaxSubtotal = rAttribs.getBool( XML_maxSubtotal, false );
278  maModel.mbMinSubtotal = rAttribs.getBool( XML_minSubtotal, false );
279  maModel.mbProductSubtotal = rAttribs.getBool( XML_productSubtotal, false );
280  maModel.mbCountSubtotal = rAttribs.getBool( XML_countSubtotal, false );
281  maModel.mbStdDevSubtotal = rAttribs.getBool( XML_stdDevSubtotal, false );
282  maModel.mbStdDevPSubtotal = rAttribs.getBool( XML_stdDevPSubtotal, false );
283  maModel.mbVarSubtotal = rAttribs.getBool( XML_varSubtotal, false );
284  maModel.mbVarPSubtotal = rAttribs.getBool( XML_varPSubtotal, false );
285  maModel.mbShowAll = rAttribs.getBool( XML_showAll, true );
286  maModel.mbOutline = rAttribs.getBool( XML_outline, true );
287  maModel.mbSubtotalTop = rAttribs.getBool( XML_subtotalTop, true );
288  maModel.mbInsertBlankRow = rAttribs.getBool( XML_insertBlankRow, false );
289  maModel.mbInsertPageBreak = rAttribs.getBool( XML_insertPageBreak, false );
290  maModel.mbAutoShow = rAttribs.getBool( XML_autoShow, false );
291  maModel.mbTopAutoShow = rAttribs.getBool( XML_topAutoShow, true );
292  maModel.mbMultiPageItems = rAttribs.getBool( XML_multipleItemSelectionAllowed, false );
293 }
294 
296 {
297  PTFieldItemModel aModel;
298  aModel.mnCacheItem = rAttribs.getInteger( XML_x, -1 );
299  aModel.mnType = rAttribs.getToken( XML_t, XML_data );
300  aModel.mbShowDetails = rAttribs.getBool( XML_sd, true );
301  aModel.mbHidden = rAttribs.getBool( XML_h, false );
302  aModel.msCaption = rAttribs.getXString( XML_n, OUString() );
303  maItems.push_back( aModel );
304 }
305 
307 {
308  // field index is stored as unsigned integer
309  maModel.mnSortRefField = static_cast< sal_Int32 >( rAttribs.getUnsigned( XML_field, SAL_MAX_UINT32 ) );
310 }
311 
313 {
314  maModel.mnSortRefItem = rAttribs.getInteger( XML_v, -1 );
315 }
316 
318 {
319  sal_uInt32 nFlags1, nFlags2;
320  nFlags1 = rStrm.readuInt32();
321  maModel.mnNumFmtId = rStrm.readInt32();
322  nFlags2 = rStrm.readuInt32();
325 
326  maModel.setBiffAxis( extractValue< sal_uInt8 >( nFlags1, 0, 3 ) );
327  maModel.mbDataField = getFlag( nFlags1, BIFF12_PTFIELD_DATAFIELD );
328  maModel.mbDefaultSubtotal = getFlag( nFlags1, BIFF12_PTFIELD_DEFAULT );
329  maModel.mbSumSubtotal = getFlag( nFlags1, BIFF12_PTFIELD_SUM );
330  maModel.mbCountASubtotal = getFlag( nFlags1, BIFF12_PTFIELD_COUNTA );
331  maModel.mbAverageSubtotal = getFlag( nFlags1, BIFF12_PTFIELD_AVERAGE );
332  maModel.mbMaxSubtotal = getFlag( nFlags1, BIFF12_PTFIELD_MAX );
333  maModel.mbMinSubtotal = getFlag( nFlags1, BIFF12_PTFIELD_MIN );
334  maModel.mbProductSubtotal = getFlag( nFlags1, BIFF12_PTFIELD_PRODUCT );
335  maModel.mbCountSubtotal = getFlag( nFlags1, BIFF12_PTFIELD_COUNT );
336  maModel.mbStdDevSubtotal = getFlag( nFlags1, BIFF12_PTFIELD_STDDEV );
337  maModel.mbStdDevPSubtotal = getFlag( nFlags1, BIFF12_PTFIELD_STDDEVP );
338  maModel.mbVarSubtotal = getFlag( nFlags1, BIFF12_PTFIELD_VAR );
339  maModel.mbVarPSubtotal = getFlag( nFlags1, BIFF12_PTFIELD_VARP );
340 
341  maModel.mbShowAll = getFlag( nFlags2, BIFF12_PTFIELD_SHOWALL );
342  maModel.mbOutline = getFlag( nFlags2, BIFF12_PTFIELD_OUTLINE );
343  maModel.mbSubtotalTop = getFlag( nFlags2, BIFF12_PTFIELD_SUBTOTALTOP );
344  maModel.mbInsertBlankRow = getFlag( nFlags2, BIFF12_PTFIELD_INSERTBLANKROW );
345  maModel.mbInsertPageBreak = getFlag( nFlags2, BIFF12_PTFIELD_INSERTPAGEBREAK );
346  maModel.mbAutoShow = getFlag( nFlags2, BIFF12_PTFIELD_AUTOSHOW );
347  maModel.mbTopAutoShow = getFlag( nFlags2, BIFF12_PTFIELD_AUTOSHOWTOP );
348  maModel.mbMultiPageItems = getFlag( nFlags2, BIFF12_PTFIELD_MULTIPAGEITEMS );
349 
350  bool bAutoSort = getFlag( nFlags2, BIFF12_PTFIELD_AUTOSORT );
351  bool bAscending = getFlag( nFlags2, BIFF12_PTFIELD_SORTASCENDING );
352  maModel.mnSortType = bAutoSort ? (bAscending ? XML_ascending : XML_descending) : XML_manual;
353 }
354 
356 {
357  PTFieldItemModel aModel;
359  sal_uInt16 nFlags;
360  nType = rStrm.readuChar();
361  nFlags = rStrm.readuInt16();
362  aModel.mnCacheItem = rStrm.readInt32();
363 
364  aModel.setBiffType( nType );
365  aModel.mbShowDetails = !getFlag( nFlags, BIFF12_PTFITEM_HIDEDETAILS );
366  aModel.mbHidden = getFlag( nFlags, BIFF12_PTFITEM_HIDDEN );
367 
368  maItems.push_back( aModel );
369 }
370 
372 {
373  maModel.mnSortRefField = rStrm.readInt32();
374 }
375 
377 {
378  maModel.mnSortRefItem = rStrm.readInt32();
379 }
380 
381 void PivotTableField::finalizeImport( const Reference< XDataPilotDescriptor >& rxDPDesc )
382 {
383  /* Process all fields based on source data, other fields (e.g. group
384  fields) are processed from here. PivotCache::getCacheDatabaseIndex()
385  returns -1 for all fields not based on source data. */
386  Reference< XDataPilotField > xDPField;
387  sal_Int32 nDatabaseIdx = mrPivotTable.getCacheDatabaseIndex( mnFieldIndex );
388  if( !((nDatabaseIdx >= 0) && rxDPDesc.is()) )
389  return;
390 
391  try
392  {
393  // try to get the source field and its name from passed DataPilot descriptor
394  Reference< XIndexAccess > xDPFieldsIA( rxDPDesc->getDataPilotFields(), UNO_SET_THROW );
395  xDPField.set( xDPFieldsIA->getByIndex( nDatabaseIdx ), UNO_QUERY_THROW );
396  Reference< XNamed > xDPFieldName( xDPField, UNO_QUERY_THROW );
397  maDPFieldName = xDPFieldName->getName();
398  OSL_ENSURE( !maDPFieldName.isEmpty(), "PivotTableField::finalizeImport - no field name in source data found" );
399 
400  // try to convert grouping settings
401  if( const PivotCacheField* pCacheField = mrPivotTable.getCacheField( mnFieldIndex ) )
402  {
403  // numeric grouping is done inplace, no nested group fields will appear
404  if( pCacheField->hasNumericGrouping() )
405  {
406  pCacheField->convertNumericGrouping( xDPField );
407  }
408  else if( pCacheField->hasDateGrouping() )
409  {
410  // first date group settings are inplace
411  pCacheField->createDateGroupField( xDPField );
412  // create all nested group fields (if any)
414  }
415  else if( pCacheField->hasParentGrouping() )
416  {
417 
418  // create a list of all item names, needed to map between original and group items
419  ::std::vector< OUString > aItems;
420  pCacheField->getCacheItemNames( aItems );
421  PivotCacheGroupItemVector aItemNames;
422  for( const auto& rItem : aItems )
423  aItemNames.emplace_back( rItem );
424  // create all nested group fields (if any)
425  mrPivotTable.finalizeParentGroupingImport( xDPField, *pCacheField, aItemNames );
426  }
427  }
428  }
429  catch( Exception& )
430  {
431  }
432 }
433 
434 void PivotTableField::finalizeDateGroupingImport( const Reference< XDataPilotField >& rxBaseDPField, sal_Int32 nBaseFieldIdx )
435 {
436  if( maDPFieldName.isEmpty() ) // prevent endless loops if file format is broken
437  {
439  {
440  if( !pCacheField->isDatabaseField() && pCacheField->hasDateGrouping() && (pCacheField->getGroupBaseField() == nBaseFieldIdx) )
441  {
442  maDPFieldName = pCacheField->createDateGroupField( rxBaseDPField );
443  pCacheField->setFinalGroupName(maDPFieldName);
444  OSL_ENSURE( !maDPFieldName.isEmpty(), "PivotTableField::finalizeDateGroupingImport - cannot create date group field" );
445  }
446  }
447  }
448 }
449 
450 void PivotTableField::finalizeParentGroupingImport( const Reference< XDataPilotField >& rxBaseDPField, const PivotCacheField& rBaseCacheField, PivotCacheGroupItemVector& orItemNames )
451 {
452  if( !maDPFieldName.isEmpty() ) // prevent endless loops if file format is broken
453  return;
454 
456  if( !pCacheField )
457  return;
458 
459  // data field can have user defined groupname captions, apply them
460  // if they do
461  IdCaptionPairList captionList;
462  for( const auto& rItem : maItems )
463  {
464  if ( rItem.mnType == XML_data && rItem.msCaption.getLength() )
465  captionList.emplace_back( rItem.mnCacheItem, rItem.msCaption );
466  }
467  if ( !captionList.empty() )
468  pCacheField->applyItemCaptions( captionList );
469 
470  maDPFieldName = pCacheField->createParentGroupField( rxBaseDPField, rBaseCacheField, orItemNames );
471  pCacheField->setFinalGroupName(maDPFieldName);
472  // on success, try to create nested group fields
473  Reference< XDataPilotField > xDPField = mrPivotTable.getDataPilotField( maDPFieldName );
474  if( xDPField.is() )
475  mrPivotTable.finalizeParentGroupingImport( xDPField, *pCacheField, orItemNames );
476 }
477 
478 void PivotTableField::finalizeImportBasedOnCache( const Reference< XDataPilotDescriptor >& rxDPDesc)
479 {
480  /* Process all fields based on source data, other fields (e.g. group
481  fields) are processed based on cache fields.*/
482  Reference< XDataPilotField > xDPField;
483  sal_Int32 nDatabaseIdx = mrPivotTable.getCacheDatabaseIndex( mnFieldIndex );
484  if( (nDatabaseIdx >= 0) && rxDPDesc.is() ) try
485  {
486  // Try to get the source field and its name from passed DataPilot descriptor
487  Reference< XIndexAccess > xDPFieldsIA( rxDPDesc->getDataPilotFields(), UNO_SET_THROW );
488  xDPField.set( xDPFieldsIA->getByIndex( nDatabaseIdx ), UNO_QUERY_THROW );
489  Reference< XNamed > xDPFieldName( xDPField, UNO_QUERY_THROW );
490  maDPFieldName = xDPFieldName->getName();
491  SAL_WARN_IF( maDPFieldName.isEmpty(), "sc.filter", "PivotTableField::finalizeImportBasedOnCache - no field name in source data found" );
492  }
493  catch( Exception& )
494  {
495  }
496 
497  // Use group names already generated for another table using the same group field.
498  if( const PivotCacheField* pCacheField = mrPivotTable.getCacheField( mnFieldIndex ) )
499  {
500  if(!pCacheField->getFinalGroupName().isEmpty())
501  maDPFieldName = pCacheField->getFinalGroupName();
502  }
503 }
504 
506 {
507  convertRowColPageField( XML_axisRow );
508 }
509 
511 {
512  convertRowColPageField( XML_axisCol );
513 }
514 
516 {
518 }
519 
521 {
522  OSL_ENSURE( rPageField.mnField == mnFieldIndex, "PivotTableField::convertPageField - wrong field index" );
523  // convert all settings common for row/column/page fields
524  Reference< XDataPilotField > xDPField = convertRowColPageField( XML_axisPage );
525 
526  if( !xDPField.is() )
527  return;
528 
529  PropertySet aPropSet( xDPField );
530 
531  // find cache item used as 'selected page'
532  sal_Int32 nCacheItem = -1;
534  {
535  // multiple items may be selected
536  OSL_ENSURE( rPageField.mnItem == BIFF12_PTPAGEFIELD_MULTIITEMS, "PivotTableField::convertPageField - unexpected cache item index" );
537  // try to find a single visible item
538  bool bHasMultiItems = false;
539  for( const auto& rItem : maItems )
540  {
541  if( (rItem.mnType == XML_data) && !rItem.mbHidden )
542  {
543  bHasMultiItems = nCacheItem >= 0;
544  nCacheItem = bHasMultiItems ? -1 : rItem.mnCacheItem;
545  }
546 
547  if( bHasMultiItems )
548  break;
549  }
550  }
551  else
552  {
553  // single item may be selected
554  if( (0 <= rPageField.mnItem) && (rPageField.mnItem < static_cast< sal_Int32 >( maItems.size() )) )
555  nCacheItem = maItems[ rPageField.mnItem ].mnCacheItem;
556  }
557 
558  if( nCacheItem < 0 )
559  return;
560 
561  if( const PivotCacheField* pCacheField = mrPivotTable.getCacheField( mnFieldIndex ) )
562  {
563  if( const PivotCacheItem* pSharedItem = pCacheField->getCacheItem( nCacheItem ) )
564  {
565  ScDPObject* pDPObj = mrPivotTable.getDPObject();
566  ScDPSaveData* pSaveData = pDPObj->GetSaveData();
567  ScDPSaveDimension* pDim = pSaveData->GetDimensionByName(pCacheField->getName());
568  OUString aSelectedPage = pSharedItem->getFormattedName(*pDim, pDPObj, DateTime(getWorkbookSettings().getNullDate()));
569  aPropSet.setProperty( PROP_SelectedPage, aSelectedPage );
570  }
571  }
572 }
573 
575 {
576  OSL_ENSURE( rDataField.mnField == mnFieldIndex, "PivotTableField::convertDataField - wrong field index" );
577  OSL_ENSURE( maModel.mbDataField, "PivotTableField::convertDataField - not a data field" );
578  Reference< XDataPilotField > xDPField = mrPivotTable.getDataPilotField( maDPFieldName );
579  if( !xDPField.is() )
580  return;
581 
582  PropertySet aPropSet( xDPField );
583 
584  // field orientation
585  aPropSet.setProperty( PROP_Orientation, DataPilotFieldOrientation_DATA );
586 
587  if (!rDataField.maName.isEmpty())
588  aPropSet.setProperty(PROP_Name, rDataField.maName);
589 
590  /* Field aggregation function. Documentation is a little bit confused
591  about which names to use for the count functions. The name 'count'
592  means 'count all', and 'countNum' means 'count numbers'. On the
593  other hand, for subtotals, 'countA' means 'count all', and 'count'
594  means 'count numbers' (see above). */
595  GeneralFunction eAggFunc = GeneralFunction_SUM;
596  switch( rDataField.mnSubtotal )
597  {
598  case XML_sum: eAggFunc = GeneralFunction_SUM; break;
599  case XML_count: eAggFunc = GeneralFunction_COUNT; break;
600  case XML_average: eAggFunc = GeneralFunction_AVERAGE; break;
601  case XML_max: eAggFunc = GeneralFunction_MAX; break;
602  case XML_min: eAggFunc = GeneralFunction_MIN; break;
603  case XML_product: eAggFunc = GeneralFunction_PRODUCT; break;
604  case XML_countNums: eAggFunc = GeneralFunction_COUNTNUMS; break;
605  case XML_stdDev: eAggFunc = GeneralFunction_STDEV; break;
606  case XML_stdDevp: eAggFunc = GeneralFunction_STDEVP; break;
607  case XML_var: eAggFunc = GeneralFunction_VAR; break;
608  case XML_varp: eAggFunc = GeneralFunction_VARP; break;
609  default: OSL_FAIL( "PivotTableField::convertDataField - unknown aggregation function" );
610  }
611  aPropSet.setProperty( PROP_Function, eAggFunc );
612 
613  // field reference ('show data as')
614  DataPilotFieldReference aReference;
615  aReference.ReferenceType = DataPilotFieldReferenceType::NONE;
616  switch( rDataField.mnShowDataAs )
617  {
618  case XML_difference: aReference.ReferenceType = DataPilotFieldReferenceType::ITEM_DIFFERENCE; break;
619  case XML_percent: aReference.ReferenceType = DataPilotFieldReferenceType::ITEM_PERCENTAGE; break;
620  case XML_percentDiff: aReference.ReferenceType = DataPilotFieldReferenceType::ITEM_PERCENTAGE_DIFFERENCE; break;
621  case XML_runTotal: aReference.ReferenceType = DataPilotFieldReferenceType::RUNNING_TOTAL; break;
622  case XML_percentOfRow: aReference.ReferenceType = DataPilotFieldReferenceType::ROW_PERCENTAGE; break;
623  case XML_percentOfCol: aReference.ReferenceType = DataPilotFieldReferenceType::COLUMN_PERCENTAGE; break;
624  case XML_percentOfTotal: aReference.ReferenceType = DataPilotFieldReferenceType::TOTAL_PERCENTAGE; break;
625  case XML_index: aReference.ReferenceType = DataPilotFieldReferenceType::INDEX; break;
626  }
627  if( aReference.ReferenceType == DataPilotFieldReferenceType::NONE )
628  return;
629 
630  const PivotCacheField* pCacheField = mrPivotTable.getCacheField( rDataField.mnBaseField );
631  if( !pCacheField )
632  return;
633 
634  aReference.ReferenceField = pCacheField->getName();
635  switch( rDataField.mnBaseItem )
636  {
637  case OOX_PT_PREVIOUS_ITEM:
638  aReference.ReferenceItemType = DataPilotFieldReferenceItemType::PREVIOUS;
639  break;
640  case OOX_PT_NEXT_ITEM:
641  aReference.ReferenceItemType = DataPilotFieldReferenceItemType::NEXT;
642  break;
643  default:
644  aReference.ReferenceItemType = DataPilotFieldReferenceItemType::NAMED;
645  if( const PivotCacheItem* pCacheItem = pCacheField->getCacheItem( rDataField.mnBaseItem ) )
646  aReference.ReferenceItemName = pCacheItem->getName();
647  }
648  aPropSet.setProperty( PROP_Reference, aReference );
649 }
650 
651 // private --------------------------------------------------------------------
652 
653 Reference< XDataPilotField > PivotTableField::convertRowColPageField( sal_Int32 nAxis )
654 {
655  bool bDataLayout = mnFieldIndex == OOX_PT_DATALAYOUTFIELD;
656  Reference< XDataPilotField > xDPField = bDataLayout ? mrPivotTable.getDataLayoutField() : mrPivotTable.getDataPilotField( maDPFieldName );
657  OSL_ENSURE( bDataLayout || (nAxis == maModel.mnAxis), "PivotTableField::convertRowColPageField - field axis mismatch" );
658 
659  if( xDPField.is() )
660  {
661  // TODO: Use this to set properties directly, bypassing the slow uno layer.
662  ScDPObject* pDPObj = mrPivotTable.getDPObject();
663 
664  PropertySet aPropSet( xDPField );
665 
666  // field orientation
667  DataPilotFieldOrientation eFieldOrient = DataPilotFieldOrientation_HIDDEN;
668  switch( nAxis )
669  {
670  case XML_axisRow: eFieldOrient = DataPilotFieldOrientation_ROW; break;
671  case XML_axisCol: eFieldOrient = DataPilotFieldOrientation_COLUMN; break;
672  case XML_axisPage: eFieldOrient = DataPilotFieldOrientation_PAGE; break;
673  }
674  if( eFieldOrient != DataPilotFieldOrientation_HIDDEN )
675  aPropSet.setProperty( PROP_Orientation, eFieldOrient );
676 
677  // all other settings not for the data layout field
678  if( !bDataLayout )
679  {
680  /* Field subtotal functions. Ignore the 'defaultSubtotal' flag, if
681  explicit functions are set. This is different behaviour between
682  XML (where 'defaultSubtotal' is set regardless of other
683  functions) and binary formats (where 'defaultSubtotal' is not
684  set if other functions are set). */
685  ::std::vector< GeneralFunction > aSubtotals;
686  /* Order of subtotals is fixed in Excel. Documentation is a little
687  bit confused about which names to use for the count functions.
688  For subtotals, 'countA' means 'count all', and 'count' means
689  'count numbers'. On the other hand, for the data field
690  aggregation function, 'count' means 'count all', and 'countNum'
691  means 'count numbers' (see below). */
692  if( maModel.mbSumSubtotal ) aSubtotals.push_back( GeneralFunction_SUM );
693  if( maModel.mbCountASubtotal ) aSubtotals.push_back( GeneralFunction_COUNT );
694  if( maModel.mbAverageSubtotal ) aSubtotals.push_back( GeneralFunction_AVERAGE );
695  if( maModel.mbMaxSubtotal ) aSubtotals.push_back( GeneralFunction_MAX );
696  if( maModel.mbMinSubtotal ) aSubtotals.push_back( GeneralFunction_MIN );
697  if( maModel.mbProductSubtotal ) aSubtotals.push_back( GeneralFunction_PRODUCT );
698  if( maModel.mbCountSubtotal ) aSubtotals.push_back( GeneralFunction_COUNTNUMS );
699  if( maModel.mbStdDevSubtotal ) aSubtotals.push_back( GeneralFunction_STDEV );
700  if( maModel.mbStdDevPSubtotal ) aSubtotals.push_back( GeneralFunction_STDEVP );
701  if( maModel.mbVarSubtotal ) aSubtotals.push_back( GeneralFunction_VAR );
702  if( maModel.mbVarPSubtotal ) aSubtotals.push_back( GeneralFunction_VARP );
703  // if no function is set manually, check the 'defaultSubtotal' flag
704  if( aSubtotals.empty() && maModel.mbDefaultSubtotal )
705  aSubtotals.push_back( GeneralFunction_AUTO );
706  aPropSet.setProperty( PROP_Subtotals, comphelper::containerToSequence( aSubtotals ) );
707 
708  // layout settings
709  DataPilotFieldLayoutInfo aLayoutInfo;
710  aLayoutInfo.LayoutMode = maModel.mbOutline ?
711  (maModel.mbSubtotalTop ? DataPilotFieldLayoutMode::OUTLINE_SUBTOTALS_TOP : DataPilotFieldLayoutMode::OUTLINE_SUBTOTALS_BOTTOM) :
712  DataPilotFieldLayoutMode::TABULAR_LAYOUT;
713  aLayoutInfo.AddEmptyLines = maModel.mbInsertBlankRow;
714  aPropSet.setProperty( PROP_LayoutInfo, aLayoutInfo );
715  aPropSet.setProperty( PROP_ShowEmpty, maModel.mbShowAll );
716 
717  // auto show (OOXML/BIFF12 only)
718  if( maModel.mbAutoShow )
719  {
720  DataPilotFieldAutoShowInfo aAutoShowInfo;
721  aAutoShowInfo.IsEnabled = true;
722  aAutoShowInfo.ShowItemsMode = maModel.mbTopAutoShow ? DataPilotFieldShowItemsMode::FROM_TOP : DataPilotFieldShowItemsMode::FROM_BOTTOM;
723  aAutoShowInfo.ItemCount = maModel.mnAutoShowItems;
725  aAutoShowInfo.DataField = pCacheField->getName();
726  aPropSet.setProperty( PROP_AutoShowInfo, aAutoShowInfo );
727  }
728 
729  // auto sort
730  DataPilotFieldSortInfo aSortInfo;
731  aSortInfo.IsAscending = maModel.mnSortType == XML_ascending;
732  if( (maModel.mnSortType != XML_ascending) && (maModel.mnSortType != XML_descending) )
733  {
734  aSortInfo.Mode = DataPilotFieldSortMode::MANUAL;
735  }
736  else
737  {
738  const PivotCacheField* pCacheField = (maModel.mnSortRefField == OOX_PT_DATALAYOUTFIELD) ?
740  if( pCacheField )
741  {
742  aSortInfo.Mode = DataPilotFieldSortMode::DATA;
743  aSortInfo.Field = pCacheField->getName();
744  }
745  else
746  {
747  aSortInfo.Mode = DataPilotFieldSortMode::NAME;
748  }
749  }
750  aPropSet.setProperty( PROP_SortInfo, aSortInfo );
751 
752  // item settings
753  if (const PivotCacheField* pCacheField = mrPivotTable.getCacheField(mnFieldIndex))
754  {
755  ScDPSaveData* pSaveData = pDPObj->GetSaveData();
756  ScDPSaveDimension* pDim = pSaveData->GetDimensionByName(pCacheField->getName());
757 
758  try
759  {
760  for( const auto& rItem : maItems )
761  {
762  if (rItem.mnType != XML_data)
763  continue;
764 
765  const PivotCacheItem* pSharedItem = pCacheField->getCacheItem(rItem.mnCacheItem);
766  if (!pSharedItem)
767  continue;
768 
769  try
770  {
771  ScDPSaveMember* pMem = pDim->GetMemberByName(pSharedItem->getFormattedName(*pDim, pDPObj, DateTime(getWorkbookSettings().getNullDate())));
772  pMem->SetShowDetails(rItem.mbShowDetails);
773  pMem->SetIsVisible(!rItem.mbHidden);
774  }
775  catch( Exception& )
776  {
777  // catch every failed container access to be able to process following items
778  }
779  }
780  }
781  catch (const Exception&) {}
782  }
783  }
784  }
785  return xDPField;
786 }
787 
789  mfValue( 0.0 ),
790  mnField( -1 ),
791  mnMemPropField( -1 ),
793  mnEvalOrder( 0 ),
794  mnId( -1 ),
795  mnMeasureField( -1 ),
796  mnMeasureHier( -1 ),
797  mbTopFilter( true )
798 {
799 }
800 
802  WorkbookHelper( rPivotTable ),
803  mrPivotTable( rPivotTable )
804 {
805 }
806 
808 {
809  maModel.maName = rAttribs.getXString( XML_name, OUString() );
810  maModel.maDescription = rAttribs.getXString( XML_description, OUString() );
811  maModel.maStrValue1 = rAttribs.getXString( XML_stringValue1, OUString() );
812  maModel.maStrValue2 = rAttribs.getXString( XML_stringValue2, OUString() );
813  maModel.mnField = rAttribs.getInteger( XML_fld, -1 );
814  maModel.mnMemPropField = rAttribs.getInteger( XML_mpFld, -1 );
816  maModel.mnEvalOrder = rAttribs.getInteger( XML_evalOrder, 0 );
817  maModel.mnId = rAttribs.getInteger( XML_id, -1 );
818  maModel.mnMeasureField = rAttribs.getInteger( XML_iMeasureFld, -1 );
819  maModel.mnMeasureHier = rAttribs.getInteger( XML_iMeasureHier, -1 );
820 }
821 
823 {
824  OSL_ENSURE( rAttribs.getBool( XML_percent, false ) == (maModel.mnType == XML_percent),
825  "PivotTableFilter::importTop10 - unexpected value of percent attribute" );
826  maModel.mfValue = rAttribs.getDouble( XML_val, 0.0 );
827  maModel.mbTopFilter = rAttribs.getBool( XML_top, true );
828 }
829 
831 {
832  sal_Int32 nType;
833  sal_uInt16 nFlags;
834  maModel.mnField = rStrm.readInt32();
835  maModel.mnMemPropField = rStrm.readInt32();
836  nType = rStrm.readInt32();
837  rStrm.skip( 4 ); // unused
838  maModel.mnId = rStrm.readInt32();
839  maModel.mnMeasureField = rStrm.readInt32();
840  maModel.mnMeasureHier = rStrm.readInt32();
841  nFlags = rStrm.readuInt16();
842  if( getFlag( nFlags, BIFF12_PTFILTER_HASNAME ) )
843  rStrm >> maModel.maName;
844  if( getFlag( nFlags, BIFF12_PTFILTER_HASDESCRIPTION ) )
845  rStrm >> maModel.maDescription;
846  if( getFlag( nFlags, BIFF12_PTFILTER_HASSTRVALUE1 ) )
847  rStrm >> maModel.maStrValue1;
848  if( getFlag( nFlags, BIFF12_PTFILTER_HASSTRVALUE2 ) )
849  rStrm >> maModel.maStrValue2;
850 
851  static const sal_Int32 spnTypes[] =
852  {
853  XML_unknown,
854  // data field top10 filter (1-3)
855  XML_count, XML_percent, XML_sum,
856  // caption filter (4-17)
857  XML_captionEqual, XML_captionNotEqual,
858  XML_captionBeginsWith, XML_captionNotBeginsWith, XML_captionEndsWith, XML_captionNotEndsWith,
859  XML_captionContains, XML_captionNotContains, XML_captionGreaterThan, XML_captionGreaterThanOrEqual,
860  XML_captionLessThan, XML_captionLessThanOrEqual, XML_captionBetween, XML_captionNotBetween,
861  // value filter (18-25)
862  XML_valueEqual, XML_valueNotEqual, XML_valueGreaterThan, XML_valueGreaterThanOrEqual,
863  XML_valueLessThan, XML_valueLessThanOrEqual, XML_valueBetween, XML_valueNotBetween,
864  // date filter (26-65)
865  XML_dateEqual, XML_dateOlderThan, XML_dateNewerThan, XML_dateBetween,
866  XML_tomorrow, XML_today, XML_yesterday, XML_nextWeek, XML_thisWeek, XML_lastWeek,
867  XML_nextMonth, XML_thisMonth, XML_lastMonth, XML_nextQuarter, XML_thisQuarter, XML_lastQuarter,
868  XML_nextYear, XML_thisYear, XML_lastYear, XML_yearToDate, XML_Q1, XML_Q2, XML_Q3, XML_Q4,
869  XML_M1, XML_M2, XML_M3, XML_M4, XML_M5, XML_M6, XML_M7, XML_M8, XML_M9, XML_M10, XML_M11, XML_M12,
870  XML_dateNotEqual, XML_dateOlderThanOrEqual, XML_dateNewerThanOrEqual, XML_dateNotBetween
871  };
872  maModel.mnType = STATIC_ARRAY_SELECT( spnTypes, nType, XML_TOKEN_INVALID );
873 }
874 
876 {
877  sal_uInt8 nFlags;
878  nFlags = rStrm.readuChar();
879  maModel.mfValue = rStrm.readDouble();
880 
881  SAL_WARN_IF(
882  getFlag(nFlags, BIFF12_TOP10FILTER_PERCENT) != (maModel.mnType == XML_percent),
883  "sc.filter",
884  "PivotTableFilter::importTop10 - unexpected value of percent attribute");
885  maModel.mbTopFilter = getFlag( nFlags, BIFF12_TOP10FILTER_TOP );
886 }
887 
889 {
890  // only simple top10 filter supported
891  if( maModel.mnType != XML_count )
892  return;
893 
895  if( aPropSet.is() )
896  {
897  DataPilotFieldAutoShowInfo aAutoShowInfo;
898  aAutoShowInfo.IsEnabled = true;
899  aAutoShowInfo.ShowItemsMode = maModel.mbTopFilter ? DataPilotFieldShowItemsMode::FROM_TOP : DataPilotFieldShowItemsMode::FROM_BOTTOM;
900  aAutoShowInfo.ItemCount = getLimitedValue< sal_Int32, double >( maModel.mfValue, 0, SAL_MAX_INT32 );
902  aAutoShowInfo.DataField = pCacheField->getName();
903  aPropSet.setProperty( PROP_AutoShowInfo, aAutoShowInfo );
904  }
905 }
906 
908  mnCacheId( -1 ),
909  mnDataPosition( 0 ),
910  mnPageWrap( 0 ),
911  mnIndent( 1 ),
912  mnChartFormat( 0 ),
913  mbDataOnRows( false ),
914  mbShowError( false ),
915  mbShowMissing( true ),
916  mbShowItems( true ),
917  mbDisableFieldList( false ),
918  mbShowCalcMembers( true ),
919  mbVisualTotals( true ),
920  mbShowDrill( true ),
921  mbPrintDrill( false ),
922  mbEnableDrill( true ),
923  mbPreserveFormatting( true ),
924  mbUseAutoFormat( false ),
925  mbPageOverThenDown( false ),
926  mbSubtotalHiddenItems( false ),
927  mbRowGrandTotals( true ),
928  mbColGrandTotals( true ),
929  mbFieldPrintTitles( false ),
930  mbItemPrintTitles( false ),
931  mbMergeItem( false ),
932  mbShowEmptyRow( false ),
933  mbShowEmptyCol( false ),
934  mbShowHeaders( true ),
935  mbFieldListSortAsc( false ),
936  mbCustomListSort( true )
937 {
938 }
939 
941  mnFirstHeaderRow( 0 ),
942  mnFirstDataRow( 0 ),
943  mnFirstDataCol( 0 ),
944  mnRowPageCount( 0 ),
945  mnColPageCount( 0 )
946 {
947 }
948 
950  WorkbookHelper( rHelper ),
951  mpDPObject(nullptr),
952  maDataField( *this, OOX_PT_DATALAYOUTFIELD ),
953  mpPivotCache( nullptr )
954 {
955 }
956 
958 {
959  maDefModel.maName = rAttribs.getXString( XML_name, OUString() );
960  maDefModel.maDataCaption = rAttribs.getXString( XML_dataCaption , OUString() );
961  maDefModel.maGrandTotalCaption = rAttribs.getXString( XML_grandTotalCaption, OUString() );
962  maDefModel.maRowHeaderCaption = rAttribs.getXString( XML_rowHeaderCaption, OUString() );
963  maDefModel.maColHeaderCaption = rAttribs.getXString( XML_colHeaderCaption, OUString() );
964  maDefModel.maErrorCaption = rAttribs.getXString( XML_errorCaption, OUString() );
965  maDefModel.maMissingCaption = rAttribs.getXString( XML_missingCaption, OUString() );
966  maDefModel.maPageStyle = rAttribs.getXString( XML_pageStyle, OUString() );
967  maDefModel.maPivotTableStyle = rAttribs.getXString( XML_pivotTableStyle, OUString() );
968  maDefModel.maVacatedStyle = rAttribs.getXString( XML_vacatedStyle, OUString() );
969  maDefModel.maTag = rAttribs.getXString( XML_tag, OUString() );
970  maDefModel.mnCacheId = rAttribs.getInteger( XML_cacheId, -1 );
971  maDefModel.mnDataPosition = rAttribs.getInteger( XML_dataPosition, 0 );
972  maDefModel.mnPageWrap = rAttribs.getInteger( XML_pageWrap, 0 );
973  maDefModel.mnIndent = rAttribs.getInteger( XML_indent, 1 );
974  maDefModel.mnChartFormat = rAttribs.getInteger( XML_chartFormat, 0 );
975  maDefModel.mnAutoFormatId = rAttribs.getInteger( XML_autoFormatId, 0 );
976  maDefModel.mbDataOnRows = rAttribs.getBool( XML_dataOnRows, false );
977  maDefModel.mbShowError = rAttribs.getBool( XML_showError, false );
978  maDefModel.mbShowMissing = rAttribs.getBool( XML_showMissing, true );
979  maDefModel.mbShowItems = rAttribs.getBool( XML_showItems, true );
980  maDefModel.mbDisableFieldList = rAttribs.getBool( XML_disableFieldList, false );
981  maDefModel.mbShowCalcMembers = rAttribs.getBool( XML_showCalcMbrs, true );
982  maDefModel.mbVisualTotals = rAttribs.getBool( XML_visualTotals, true );
983  maDefModel.mbShowDrill = rAttribs.getBool( XML_showDrill, true );
984  maDefModel.mbPrintDrill = rAttribs.getBool( XML_printDrill, false );
985  maDefModel.mbEnableDrill = rAttribs.getBool( XML_enableDrill, true );
986  maDefModel.mbPreserveFormatting = rAttribs.getBool( XML_preserveFormatting, true );
987  maDefModel.mbUseAutoFormat = rAttribs.getBool( XML_useAutoFormatting, false );
988  maDefModel.mbPageOverThenDown = rAttribs.getBool( XML_pageOverThenDown, false );
989  maDefModel.mbSubtotalHiddenItems = rAttribs.getBool( XML_subtotalHiddenItems, false );
990  maDefModel.mbRowGrandTotals = rAttribs.getBool( XML_rowGrandTotals, true );
991  maDefModel.mbColGrandTotals = rAttribs.getBool( XML_colGrandTotals, true );
992  maDefModel.mbFieldPrintTitles = rAttribs.getBool( XML_fieldPrintTitles, false );
993  maDefModel.mbItemPrintTitles = rAttribs.getBool( XML_itemPrintTitles, false );
994  maDefModel.mbMergeItem = rAttribs.getBool( XML_mergeItem, false );
995  maDefModel.mbShowEmptyRow = rAttribs.getBool( XML_showEmptyRow, false );
996  maDefModel.mbShowEmptyCol = rAttribs.getBool( XML_showEmptyCol, false );
997  maDefModel.mbShowHeaders = rAttribs.getBool( XML_showHeaders, true );
998  maDefModel.mbFieldListSortAsc = rAttribs.getBool( XML_fieldListSortAscending, false );
999  maDefModel.mbCustomListSort = rAttribs.getBool( XML_customListSort, true );
1000  maDefModel.mbApplyNumFmt = rAttribs.getBool( XML_applyNumberFormats, false );
1001  maDefModel.mbApplyFont = rAttribs.getBool( XML_applyFontFormats, false );
1002  maDefModel.mbApplyAlignment = rAttribs.getBool( XML_applyAlignmentFormats, false );
1003  maDefModel.mbApplyBorder = rAttribs.getBool( XML_applyBorderFormats, false );
1004  maDefModel.mbApplyFill = rAttribs.getBool( XML_applyPatternFormats, false );
1005  // OOXML and BIFF12 documentation differ: OOXML mentions width/height, BIFF12 mentions protection
1006  maDefModel.mbApplyProtection = rAttribs.getBool( XML_applyWidthHeightFormats, false );
1007 }
1008 
1009 void PivotTable::importLocation( const AttributeList& rAttribs, sal_Int16 nSheet )
1010 {
1011  AddressConverter::convertToCellRangeUnchecked( maLocationModel.maRange, rAttribs.getString( XML_ref, OUString() ), nSheet );
1012  maLocationModel.mnFirstHeaderRow = rAttribs.getInteger( XML_firstHeaderRow, 0 );
1013  maLocationModel.mnFirstDataRow = rAttribs.getInteger( XML_firstDataRow, 0 );
1014  maLocationModel.mnFirstDataCol = rAttribs.getInteger( XML_firstDataCol, 0 );
1015  maLocationModel.mnRowPageCount = rAttribs.getInteger( XML_rowPageCount, 0 );
1016  maLocationModel.mnColPageCount = rAttribs.getInteger( XML_colPageCount, 0 );
1017 }
1018 
1020 {
1021  importField( maRowFields, rAttribs );
1022 }
1023 
1025 {
1026  importField( maColFields, rAttribs );
1027 }
1028 
1030 {
1031  PTPageFieldModel aModel;
1032  aModel.maName = rAttribs.getXString( XML_name, OUString() );
1033  aModel.mnField = rAttribs.getInteger( XML_fld, -1 );
1034  // specification is wrong, XML_item is not the cache item, but the field item
1035  aModel.mnItem = rAttribs.getInteger( XML_item, BIFF12_PTPAGEFIELD_MULTIITEMS );
1036  maPageFields.push_back( aModel );
1037 }
1038 
1040 {
1041  PTDataFieldModel aModel;
1042  aModel.maName = rAttribs.getXString( XML_name, OUString() );
1043  aModel.mnField = rAttribs.getInteger( XML_fld, -1 );
1044  aModel.mnSubtotal = rAttribs.getToken( XML_subtotal, XML_sum );
1045  aModel.mnShowDataAs = rAttribs.getToken( XML_showDataAs, XML_normal );
1046  aModel.mnBaseField = rAttribs.getInteger( XML_baseField, -1 );
1047  aModel.mnBaseItem = rAttribs.getInteger( XML_baseItem, -1 );
1048  aModel.mnNumFmtId = rAttribs.getInteger( XML_numFmtId, 0 );
1049  maDataFields.push_back( aModel );
1050 }
1051 
1052 void PivotTable::putToInteropGrabBag(const OUString& sName, const AttributeList& rAttribs)
1053 {
1054  if (auto xFastAttributeList = rAttribs.getFastAttributeList())
1055  {
1056  // Store both known and unknown attribute sequences to the grab bag as is
1057  css::uno::Sequence<css::xml::FastAttribute> aFast = xFastAttributeList->getFastAttributes();
1058  css::uno::Sequence<css::xml::Attribute> aUnk = xFastAttributeList->getUnknownAttributes();
1059  css::uno::Sequence<css::uno::Any> aVal{ css::uno::Any(aFast), css::uno::Any(aUnk) };
1060  maInteropGrabBag[sName] <<= aVal;
1061  }
1062 }
1063 
1065 {
1066  sal_uInt32 nFlags1, nFlags2, nFlags3;
1067  sal_uInt8 nDataAxis;
1068  nFlags1 = rStrm.readuInt32();
1069  nFlags2 = rStrm.readuInt32();
1070  nFlags3 = rStrm.readuInt32();
1071  nDataAxis = rStrm.readuChar();
1072  maDefModel.mnPageWrap = rStrm.readuInt8();
1073  rStrm.skip( 2 ); // refresh versions
1076  rStrm.skip( 2 ); // unused
1078  maDefModel.mnCacheId = rStrm.readInt32();
1079  rStrm >> maDefModel.maName;
1080  if( getFlag( nFlags2, BIFF12_PTDEF_HASDATACAPTION ) )
1081  rStrm >> maDefModel.maDataCaption;
1082  if( getFlag( nFlags2, BIFF12_PTDEF_HASGRANDTOTALCAPTION ) )
1084  if( !getFlag( nFlags3, BIFF12_PTDEF_NOERRORCAPTION ) ) // missing flag indicates existing string
1085  rStrm >> maDefModel.maErrorCaption;
1086  if( !getFlag( nFlags3, BIFF12_PTDEF_NOMISSINGCAPTION ) ) // missing flag indicates existing string
1087  rStrm >> maDefModel.maMissingCaption;
1088  if( getFlag( nFlags2, BIFF12_PTDEF_HASPAGESTYLE ) )
1089  rStrm >> maDefModel.maPageStyle;
1090  if( getFlag( nFlags2, BIFF12_PTDEF_HASPIVOTTABLESTYLE ) )
1091  rStrm >> maDefModel.maPivotTableStyle;
1092  if( getFlag( nFlags2, BIFF12_PTDEF_HASVACATEDSTYLE ) )
1093  rStrm >> maDefModel.maVacatedStyle;
1094  if( getFlag( nFlags2, BIFF12_PTDEF_HASTAG ) )
1095  rStrm >> maDefModel.maTag;
1096  if( getFlag( nFlags3, BIFF12_PTDEF_HASCOLHEADERCAPTION ) ) // TODO: right order (col/row)? spec is unclear
1097  rStrm >> maDefModel.maColHeaderCaption;
1098  if( getFlag( nFlags3, BIFF12_PTDEF_HASROWHEADERCAPTION ) )
1099  rStrm >> maDefModel.maRowHeaderCaption;
1100 
1101  SAL_WARN_IF(
1102  (nDataAxis != BIFF12_PTDEF_ROWAXIS) && (nDataAxis != BIFF12_PTDEF_COLAXIS),
1103  "sc.filter",
1104  "PivotTable::importPTDefinition - unexpected axis position for data field");
1105 
1106  maDefModel.mnIndent = extractValue< sal_uInt8 >( nFlags1, 24, 7 );
1107  maDefModel.mbDataOnRows = nDataAxis == BIFF12_PTDEF_ROWAXIS;
1108  maDefModel.mbShowError = getFlag( nFlags2, BIFF12_PTDEF_SHOWERROR );
1109  maDefModel.mbShowMissing = getFlag( nFlags2, BIFF12_PTDEF_SHOWMISSING );
1110  maDefModel.mbShowItems = getFlag( nFlags1, BIFF12_PTDEF_SHOWITEMS );
1111  maDefModel.mbDisableFieldList = getFlag( nFlags1, BIFF12_PTDEF_DISABLEFIELDLIST );
1112  maDefModel.mbShowCalcMembers = !getFlag( nFlags1, BIFF12_PTDEF_HIDECALCMEMBERS );
1113  maDefModel.mbVisualTotals = !getFlag( nFlags1, BIFF12_PTDEF_WITHHIDDENTOTALS );
1114  maDefModel.mbShowDrill = !getFlag( nFlags1, BIFF12_PTDEF_HIDEDRILL );
1115  maDefModel.mbPrintDrill = getFlag( nFlags1, BIFF12_PTDEF_PRINTDRILL );
1116  maDefModel.mbEnableDrill = getFlag( nFlags2, BIFF12_PTDEF_ENABLEDRILL );
1117  maDefModel.mbPreserveFormatting = getFlag( nFlags2, BIFF12_PTDEF_PRESERVEFORMATTING );
1118  maDefModel.mbUseAutoFormat = getFlag( nFlags2, BIFF12_PTDEF_USEAUTOFORMAT );
1119  maDefModel.mbPageOverThenDown = getFlag( nFlags2, BIFF12_PTDEF_PAGEOVERTHENDOWN );
1120  maDefModel.mbSubtotalHiddenItems = getFlag( nFlags2, BIFF12_PTDEF_SUBTOTALHIDDENITEMS );
1121  maDefModel.mbRowGrandTotals = getFlag( nFlags2, BIFF12_PTDEF_ROWGRANDTOTALS );
1122  maDefModel.mbColGrandTotals = getFlag( nFlags2, BIFF12_PTDEF_COLGRANDTOTALS );
1123  maDefModel.mbFieldPrintTitles = getFlag( nFlags2, BIFF12_PTDEF_FIELDPRINTTITLES );
1124  maDefModel.mbItemPrintTitles = getFlag( nFlags2, BIFF12_PTDEF_ITEMPRINTTITLES );
1125  maDefModel.mbMergeItem = getFlag( nFlags2, BIFF12_PTDEF_MERGEITEM );
1126  maDefModel.mbApplyNumFmt = getFlag( nFlags2, BIFF12_PTDEF_APPLYNUMFMT );
1127  maDefModel.mbApplyFont = getFlag( nFlags2, BIFF12_PTDEF_APPLYFONT );
1128  maDefModel.mbApplyAlignment = getFlag( nFlags2, BIFF12_PTDEF_APPLYALIGNMENT );
1129  maDefModel.mbApplyBorder = getFlag( nFlags2, BIFF12_PTDEF_APPLYBORDER );
1130  maDefModel.mbApplyFill = getFlag( nFlags2, BIFF12_PTDEF_APPLYFILL );
1131  maDefModel.mbApplyProtection = getFlag( nFlags2, BIFF12_PTDEF_APPLYPROTECTION );
1132  maDefModel.mbShowEmptyRow = getFlag( nFlags2, BIFF12_PTDEF_SHOWEMPTYROW );
1133  maDefModel.mbShowEmptyCol = getFlag( nFlags2, BIFF12_PTDEF_SHOWEMPTYCOL );
1134  maDefModel.mbShowHeaders = !getFlag( nFlags1, BIFF12_PTDEF_HIDEHEADERS );
1135  maDefModel.mbFieldListSortAsc = getFlag( nFlags3, BIFF12_PTDEF_FIELDLISTSORTASC );
1136  maDefModel.mbCustomListSort = !getFlag( nFlags3, BIFF12_PTDEF_NOCUSTOMLISTSORT );
1137 }
1138 
1139 void PivotTable::importPTLocation( SequenceInputStream& rStrm, sal_Int16 nSheet )
1140 {
1141  BinRange aBinRange;
1142  rStrm >> aBinRange;
1149 }
1150 
1152 {
1153  importFields( maRowFields, rStrm );
1154 }
1155 
1157 {
1158  importFields( maColFields, rStrm );
1159 }
1160 
1162 {
1163  PTPageFieldModel aModel;
1164  sal_uInt8 nFlags;
1165  aModel.mnField = rStrm.readInt32();
1166  aModel.mnItem = rStrm.readInt32();
1167  rStrm.skip( 4 ); // hierarchy
1168  nFlags = rStrm.readuChar();
1169  if( getFlag( nFlags, BIFF12_PTPAGEFIELD_HASNAME ) )
1170  rStrm >> aModel.maName;
1171  maPageFields.push_back( aModel );
1172 }
1173 
1175 {
1176  PTDataFieldModel aModel;
1177  sal_Int32 nSubtotal, nShowDataAs;
1178  sal_uInt8 nHasName;
1179  aModel.mnField = rStrm.readInt32( );
1180  nSubtotal = rStrm.readInt32();
1181  nShowDataAs = rStrm.readInt32();
1182  aModel.mnBaseField = rStrm.readInt32();
1183  aModel.mnBaseItem = rStrm.readInt32();
1184  aModel.mnNumFmtId = rStrm.readInt32();
1185  nHasName = rStrm.readuChar();
1186  if( nHasName == 1 )
1187  rStrm >> aModel.maName;
1188  aModel.setBiffSubtotal( nSubtotal );
1189  aModel.setBiffShowDataAs( nShowDataAs );
1190  maDataFields.push_back( aModel );
1191 }
1192 
1194 {
1195  sal_Int32 nFieldIndex = static_cast< sal_Int32 >( maFields.size() );
1196  PivotTableFieldVector::value_type xTableField = std::make_shared<PivotTableField>( *this, nFieldIndex );
1197  maFields.push_back( xTableField );
1198  return *xTableField;
1199 }
1200 
1202 {
1203  PivotTableFilterVector::value_type xTableFilter = std::make_shared<PivotTableFilter>( *this );
1204  maFilters.push_back( xTableFilter );
1205  return *xTableFilter;
1206 }
1207 
1209 {
1210  if( !getAddressConverter().validateCellRange( maLocationModel.maRange, true, true ) )
1211  return;
1212 
1214  if( !mpPivotCache || !mpPivotCache->isValidDataSource() || maDefModel.maName.isEmpty() )
1215  return;
1216 
1217  // clear destination area of the original pivot table
1218  try
1219  {
1220  Reference< XSheetOperation > xSheetOp( getCellRangeFromDoc( maLocationModel.maRange ), UNO_QUERY_THROW );
1221  using namespace ::com::sun::star::sheet::CellFlags;
1222  xSheetOp->clearContents( VALUE | DATETIME | STRING | FORMULA | HARDATTR | STYLES | EDITATTR | FORMATTED );
1223  }
1224  catch( Exception& )
1225  {
1226  }
1227 
1228  try
1229  {
1230  // create a new data pilot descriptor based on the source data
1231  Reference< XDataPilotTablesSupplier > xDPTablesSupp( getSheetFromDoc( maLocationModel.maRange.aStart.Tab() ), UNO_QUERY_THROW );
1232  Reference< XDataPilotTables > xDPTables( xDPTablesSupp->getDataPilotTables(), UNO_SET_THROW );
1233  mxDPDescriptor.set( xDPTables->createDataPilotDescriptor(), UNO_SET_THROW );
1234  ScRange aRange = mpPivotCache->getSourceRange();
1235  CellRangeAddress aCellRangeAddress( aRange.aStart.Tab(),
1236  aRange.aStart.Col(), aRange.aStart.Row(),
1237  aRange.aEnd.Col(), aRange.aEnd.Row() );
1238  mxDPDescriptor->setSourceRange( aCellRangeAddress );
1239  mxDPDescriptor->setTag( maDefModel.maTag );
1240 
1241  // TODO: This is a hack. Eventually we need to convert the whole thing to the internal API.
1242  auto pImpl = comphelper::getFromUnoTunnel<ScDataPilotDescriptorBase>(mxDPDescriptor);
1243  if (!pImpl)
1244  return;
1245 
1246  mpDPObject = pImpl->GetDPObject();
1247  if (!mpDPObject)
1248  return;
1249 
1250  // global data pilot properties
1251  PropertySet aDescProp( mxDPDescriptor );
1252  aDescProp.setProperty( PROP_ColumnGrand, maDefModel.mbColGrandTotals );
1253  aDescProp.setProperty( PROP_RowGrand, maDefModel.mbRowGrandTotals );
1254  aDescProp.setProperty( PROP_ShowFilterButton, false );
1255  aDescProp.setProperty( PROP_DrillDownOnDoubleClick, maDefModel.mbEnableDrill );
1256 
1257  // finalize all fields, this finds field names and creates grouping fields
1259 
1260  // all row fields
1261  for( const auto& rRowField : maRowFields )
1262  if( PivotTableField* pField = getTableField( rRowField ) )
1263  pField->convertRowField();
1264 
1265  // all column fields
1266  for( const auto& rColField : maColFields )
1267  if( PivotTableField* pField = getTableField( rColField ) )
1268  pField->convertColField();
1269 
1270  // all page fields
1271  for( const auto& rPageField : maPageFields )
1272  if( PivotTableField* pField = getTableField( rPageField.mnField ) )
1273  pField->convertPageField( rPageField );
1274 
1275  // all hidden fields
1276  ::std::set< sal_Int32 > aVisFields;
1277  aVisFields.insert( maRowFields.begin(), maRowFields.end() );
1278  aVisFields.insert( maColFields.begin(), maColFields.end() );
1279  for( const auto& rPageField : maPageFields )
1280  aVisFields.insert( rPageField.mnField );
1281  sal_Int32 nIndex = 0;
1282  for( auto& rxField : maFields )
1283  {
1284  if( aVisFields.count( nIndex ) == 0 )
1285  rxField->convertHiddenField();
1286  ++nIndex;
1287  }
1288 
1289  // all data fields
1290  for( auto& rDataField : maDataFields )
1291  {
1292  if( const PivotCacheField* pCacheField = getCacheField( rDataField.mnField ) )
1293  {
1294  if ( pCacheField-> getGroupBaseField() != -1 )
1295  rDataField.mnField = pCacheField-> getGroupBaseField();
1296  }
1297  if( PivotTableField* pField = getTableField( rDataField.mnField ) )
1298  pField->convertDataField( rDataField );
1299  }
1300 
1301  // filters
1303 
1304  // calculate base position of table
1306  /* If page fields exist, include them into the destination
1307  area (they are excluded in Excel). Add an extra blank row. */
1308  if( !maPageFields.empty() )
1309  aPos.Row = ::std::max< sal_Int32 >( static_cast< sal_Int32 >( aPos.Row - maPageFields.size() - 1 ), 0 );
1310 
1311  // save interop grab bag
1313 
1314  // insert the DataPilot table into the sheet
1315  xDPTables->insertNewByName( maDefModel.maName, aPos, mxDPDescriptor );
1316  }
1317  catch( Exception& )
1318  {
1319  TOOLS_WARN_EXCEPTION( "sc", "PivotTable::finalizeImport - exception while creating the DataPilot table" );
1320  }
1321 }
1322 
1324 {
1325  if (maFields.empty())
1326  return;
1327 
1328  /* Check whether group fields are already imported for another table
1329  sharing the same groups. */
1330  ScDPObject* pDPObj = getDPObject();
1331  const ScDocument& rDoc = getDocImport().getDoc();
1332  if (rDoc.HasPivotTable())
1333  {
1334  const ScDPCollection* pDPCollection = rDoc.GetDPCollection();
1335  assert(pDPCollection != nullptr);
1336  const ScDPDimensionSaveData* pGroups = nullptr;
1337  bool bRefFound = pDPCollection->GetReferenceGroups(*pDPObj, &pGroups);
1338  // Apply reference groups on this table.
1339  if (bRefFound && pGroups && pGroups->HasGroupDimensions()) {
1340  ScDPSaveData* pSaveData = pDPObj->GetSaveData();
1341  if (pSaveData) {
1342  pSaveData->SetDimensionData(pGroups);
1343  pDPObj->ReloadGroupTableData();
1345  return;
1346  }
1347 
1348  }
1349  }
1351 }
1352 
1353 void PivotTable::finalizeDateGroupingImport( const Reference< XDataPilotField >& rxBaseDPField, sal_Int32 nBaseFieldIdx )
1354 {
1355  // process all fields, there is no chaining information in the cache fields
1356  maFields.forEachMem( &PivotTableField::finalizeDateGroupingImport, ::std::cref(rxBaseDPField), nBaseFieldIdx );
1357 }
1358 
1359 void PivotTable::finalizeParentGroupingImport( const Reference< XDataPilotField >& rxBaseDPField,
1360  const PivotCacheField& rBaseCacheField, PivotCacheGroupItemVector& orItemNames )
1361 {
1362  // try to create parent group fields that group the items of the passed base field
1363  if( PivotTableField* pParentTableField = maFields.get( rBaseCacheField.getParentGroupField() ).get() )
1364  pParentTableField->finalizeParentGroupingImport( rxBaseDPField, rBaseCacheField, orItemNames );
1365 }
1366 
1367 Reference< XDataPilotField > PivotTable::getDataPilotField( const OUString& rFieldName ) const
1368 {
1369  Reference< XDataPilotField > xDPField;
1370  if( !rFieldName.isEmpty() && mxDPDescriptor.is() ) try
1371  {
1372  Reference< XNameAccess > xDPFieldsNA( mxDPDescriptor->getDataPilotFields(), UNO_QUERY_THROW );
1373  xDPField.set( xDPFieldsNA->getByName( rFieldName ), UNO_QUERY );
1374  }
1375  catch( Exception& )
1376  {
1377  }
1378  return xDPField;
1379 }
1380 
1381 Reference< XDataPilotField > PivotTable::getDataPilotField( sal_Int32 nFieldIdx ) const
1382 {
1383  Reference< XDataPilotField > xDPField;
1384  if( const PivotTableField* pTableField = maFields.get( nFieldIdx ).get() )
1385  xDPField = getDataPilotField( pTableField->getDPFieldName() );
1386  return xDPField;
1387 }
1388 
1389 Reference< XDataPilotField > PivotTable::getDataLayoutField() const
1390 {
1391  Reference< XDataPilotField > xDPField;
1392  try
1393  {
1394  Reference< XDataPilotDataLayoutFieldSupplier > xDPDataFieldSupp( mxDPDescriptor, UNO_QUERY_THROW );
1395  xDPField = xDPDataFieldSupp->getDataLayoutField();
1396  }
1397  catch( Exception& )
1398  {
1399  }
1400  return xDPField;
1401 }
1402 
1404 {
1405  return mpPivotCache ? mpPivotCache->getCacheField( nFieldIdx ) : nullptr;
1406 }
1407 
1408 const PivotCacheField* PivotTable::getCacheField( sal_Int32 nFieldIdx ) const
1409 {
1410  return mpPivotCache ? mpPivotCache->getCacheField( nFieldIdx ) : nullptr;
1411 }
1412 
1413 const PivotCacheField* PivotTable::getCacheFieldOfDataField( sal_Int32 nDataItemIdx ) const
1414 {
1415  const PTDataFieldModel* pDataField = ContainerHelper::getVectorElement( maDataFields, nDataItemIdx );
1416  return pDataField ? getCacheField( pDataField->mnField ) : nullptr;
1417 }
1418 
1419 sal_Int32 PivotTable::getCacheDatabaseIndex( sal_Int32 nFieldIdx ) const
1420 {
1421  return mpPivotCache ? mpPivotCache->getCacheDatabaseIndex( nFieldIdx ) : -1;
1422 }
1423 
1424 // private --------------------------------------------------------------------
1425 
1427 {
1428  return (nFieldIdx == OOX_PT_DATALAYOUTFIELD) ? &maDataField : maFields.get( nFieldIdx ).get();
1429 }
1430 
1431 void PivotTable::importField( IndexVector& orFields, const AttributeList& rAttribs )
1432 {
1433  orFields.push_back( rAttribs.getInteger( XML_x, -1 ) );
1434 }
1435 
1437 {
1438  OSL_ENSURE( orFields.empty(), "PivotTable::importFields - multiple record instances" );
1439  orFields.clear();
1440  sal_Int32 nCount = rStrm.readInt32();
1441  OSL_ENSURE( 4 * nCount == rStrm.getRemaining(), "PivotTable::importFields - invalid field count" );
1442  nCount = static_cast< sal_Int32 >( rStrm.getRemaining() / 4 );
1443  for( sal_Int32 nIdx = 0; nIdx < nCount; ++nIdx )
1444  orFields.push_back( rStrm.readInt32() );
1445 }
1446 
1448  WorkbookHelper( rHelper )
1449 {
1450 }
1451 
1453 {
1454  PivotTableVector::value_type xTable = std::make_shared<PivotTable>( *this );
1455  maTables.push_back( xTable );
1456  return *xTable;
1457 }
1458 
1460 {
1462 }
1463 
1464 } // namespace oox
1465 
1466 /* 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:809
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:497
PivotCache * mpPivotCache
Location settings of the pivot table.
ScDocumentImport & getDocImport()
OUString createParentGroupField(const css::uno::Reference< css::sheet::XDataPilotField > &rxBaseDPField, const PivotCacheField &rBaseCacheField, PivotCacheGroupItemVector &orItemNames) const
Creates a new grouped DataPilot field and returns its name.
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:163
ScDPSaveMember * GetMemberByName(const OUString &rName)
Get a member object by its name.
Definition: dpsave.cxx:457
OptValue< bool > getBool(sal_Int32 nAttrToken) const
SCROW Row() const
Definition: address.hxx:274
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:692
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:3525
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:365
bool mbStdDevPSubtotal
True = show standard deviation subtotals.
const PivotCacheItem * getCacheItem(sal_Int32 nItemIdx) const
Returns the shared or group item with the specified index.
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:498
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:96
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.
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:283
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.
XML_TOKEN_INVALID
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 TOOLS_WARN_EXCEPTION(area, stream)
#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:360
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)
void finalizeImport()
Applies the filter to the associated pivot table field if possible.
void setFinalGroupName(const OUString &rFinalGroupName)
Set the finalized group name of this field.
sal_Int32 mnShowDataAs
Subtotal aggregation function.
ScDPSaveData * GetSaveData() const
Definition: dpobject.hxx:141
XML_type
sal_Int32 mnNumFmtId
Base item for 'show data as'.
void applyItemCaptions(const IdCaptionPairList &vCaptions)
Apply user Captions to imported group data.
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:279
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:106
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).
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
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:398
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.
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.
bool m_bDetectedRangeSegmentation false
ScDocument & getDoc()
sal_Int32 mnType
Index to shared item in pivot cache.